You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.3 KiB
JavaScript
187 lines
6.3 KiB
JavaScript
|
|
|
|
import { globSync } from 'glob';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
// 脚本从项目根目录运行,因此路径是相对于根目录的。
|
|
const projectRoot = process.cwd();
|
|
const viewsPath = path.join(projectRoot, 'src', 'views');
|
|
const routerModulesPath = path.join(projectRoot, 'src', 'router', 'modules');
|
|
|
|
/**
|
|
* 从动态路由模块文件中解析出 titleArr 变量
|
|
* @param {string} filePath - 路由模块文件的路径
|
|
* @returns {Array} - 包含标题映射的数组
|
|
*/
|
|
function parseTitleArr(filePath) {
|
|
try {
|
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
const match = content.match(/const\s+titleArr\s*=\s*(\[[\s\S]*?\]);/);
|
|
if (match && match[1]) {
|
|
return new Function(`return ${match[1]}`)();
|
|
}
|
|
} catch (e) {
|
|
console.error(`读取或解析文件失败: ${filePath}`, e);
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* 从静态路由模块文件中解析出路径和标题的映射
|
|
* @param {string} filePath - 路由模块文件的路径
|
|
* @returns {Map<string, string>} - 路径名到标题的映射
|
|
*/
|
|
function parseStaticRouteTitles(filePath) {
|
|
const titleMap = new Map();
|
|
try {
|
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
const childrenMatch = content.match(/children:\s*(\[[\s\S]*?\])/);
|
|
if (!childrenMatch) return titleMap;
|
|
|
|
const routesRegex = /{\s*path:[^,]+,\s*name:[^,]+,\s*component:[^,]+,\s*meta:\s*{\s*title:\s*['|"]([\s\S]+?)['|"]/g;
|
|
let match;
|
|
while ((match = routesRegex.exec(childrenMatch[1])) !== null) {
|
|
// This is a bit of a hack, we need to get the path from the component string
|
|
const componentMatch = match[0].match(/component:\s*\(\)\s*=>\s*import\(['|"]@\/views([\s\S]+?)['|"]\)/);
|
|
if (componentMatch && componentMatch[1]) {
|
|
const routePathKey = path.basename(path.dirname(componentMatch[1]));
|
|
titleMap.set(routePathKey, match[1]);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error(`读取或解析静态路由文件失败: ${filePath}`, e);
|
|
}
|
|
return titleMap;
|
|
}
|
|
|
|
|
|
/**
|
|
* 根据新规则获取页面标题
|
|
* @param {string} file - 文件的绝对路径
|
|
* @param {Array|Map} titleSource - 标题数组或标题Map
|
|
* @returns {string} - 最终的页面标题
|
|
*/
|
|
function getTitle(file, titleSource) {
|
|
const parentDirName = path.basename(path.dirname(file));
|
|
const fileName = path.basename(file, '.vue');
|
|
const key = (fileName === 'index') ? parentDirName : fileName;
|
|
|
|
if (Array.isArray(titleSource)) { // 处理 titleArr
|
|
const foundTitle = titleSource.find(item => item.key === key);
|
|
if (foundTitle && foundTitle.title) {
|
|
return foundTitle.title;
|
|
}
|
|
} else if (titleSource instanceof Map) { // 处理静态路由的 titleMap
|
|
if (titleSource.has(key)) {
|
|
return titleSource.get(key);
|
|
}
|
|
}
|
|
|
|
// Fallback 逻辑
|
|
return key;
|
|
}
|
|
|
|
// --- 解析所有模块的标题信息 ---
|
|
const demoTitleArr = parseTitleArr(path.join(routerModulesPath, 'demo.ts'));
|
|
const pythonTitleArr = parseTitleArr(path.join(routerModulesPath, 'python.ts'));
|
|
const templateTitleMap = parseStaticRouteTitles(path.join(routerModulesPath, 'template.ts'));
|
|
|
|
// --- 统计计算 ---
|
|
|
|
let allNotes = [];
|
|
|
|
// 1. 统计 demo 模块
|
|
const demoFiles = globSync(path.join(viewsPath, 'demo', '**/*.vue')).filter(p => !p.includes('/components/'));
|
|
demoFiles.forEach(file => {
|
|
const stats = fs.statSync(file);
|
|
allNotes.push({
|
|
path: path.relative(viewsPath, file).replace(/\\/g, '/'),
|
|
title: getTitle(file, demoTitleArr),
|
|
category: 'demo',
|
|
date: stats.mtime.toISOString(),
|
|
});
|
|
});
|
|
|
|
// 2. 统计 python 模块
|
|
const pythonFiles = globSync(path.join(viewsPath, 'python', '**/*.vue'));
|
|
pythonFiles.forEach(file => {
|
|
const stats = fs.statSync(file);
|
|
allNotes.push({
|
|
path: path.relative(viewsPath, file).replace(/\\/g, '/'),
|
|
title: getTitle(file, pythonTitleArr),
|
|
category: 'python',
|
|
date: stats.mtime.toISOString(),
|
|
});
|
|
});
|
|
|
|
// 3. 统计 template 模块
|
|
const templateFiles = globSync(path.join(viewsPath, 'template', '**/*.vue')).filter(p => !p.includes('/components/'));
|
|
templateFiles.forEach(file => {
|
|
const stats = fs.statSync(file);
|
|
allNotes.push({
|
|
path: path.relative(viewsPath, file).replace(/\\/g, '/'),
|
|
title: getTitle(file, templateTitleMap),
|
|
category: 'template',
|
|
date: stats.mtime.toISOString(),
|
|
});
|
|
});
|
|
|
|
// 4. 统计 screen 和 utils (根据 remaining.ts)
|
|
const screenFile = path.join(viewsPath, 'screen', 'index.vue');
|
|
if (fs.existsSync(screenFile)) {
|
|
const stats = fs.statSync(screenFile);
|
|
allNotes.push({
|
|
path: 'screen/index.vue',
|
|
title: '大屏可视化', // 硬编码
|
|
category: 'screen',
|
|
date: stats.mtime.toISOString(),
|
|
});
|
|
}
|
|
|
|
const utilsFile = path.join(viewsPath, 'utils', 'htmlToImg.vue');
|
|
if (fs.existsSync(utilsFile)) {
|
|
const stats = fs.statSync(utilsFile);
|
|
allNotes.push({
|
|
path: 'utils/htmlToImg.vue',
|
|
title: 'html转图片', // 硬编码
|
|
category: 'utils',
|
|
date: stats.mtime.toISOString(),
|
|
});
|
|
}
|
|
|
|
// --- 数据整合 ---
|
|
|
|
allNotes.sort((a, b) => new Date(b.date) - new Date(a.date));
|
|
|
|
const categoryStats = allNotes.reduce((acc, note) => {
|
|
acc[note.category] = (acc[note.category] || 0) + 1;
|
|
return acc;
|
|
}, {});
|
|
|
|
const oneWeekAgo = new Date();
|
|
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
|
|
|
|
const weeklyAdded = allNotes.filter(note => new Date(note.date) > oneWeekAgo).length;
|
|
|
|
const finalData = {
|
|
totalNotes: allNotes.length,
|
|
categories: Object.keys(categoryStats).length,
|
|
lastUpdated: allNotes.length > 0 ? allNotes[0].date : new Date().toISOString(),
|
|
weeklyAdded: weeklyAdded,
|
|
categoryChartData: Object.entries(categoryStats).map(([name, value]) => ({ name, value })),
|
|
recentNotes: allNotes.slice(0, 5).map(note => ({
|
|
path: note.path,
|
|
title: note.title,
|
|
category: note.category,
|
|
date: note.date.split('T')[0]
|
|
}))
|
|
};
|
|
|
|
// --- 写入 JSON 文件 ---
|
|
const outputPath = path.join(viewsPath, 'welcome', 'config.json');
|
|
fs.writeFileSync(outputPath, JSON.stringify(finalData, null, 4));
|
|
|
|
console.log(`页面统计信息已成功生成到: ${outputPath}`);
|
|
console.log("分类统计:", JSON.stringify(finalData.categoryChartData, null, 4));
|