新增页面按钮目录与菜单同步三级按钮;增强我的订单(问题件/理赔件、费用、详情抽屉)、Nana 助手、联系客服、渠道问题模板及登录/RBAC 等相关功能。 Co-authored-by: Cursor <cursoragent@cursor.com>
90 lines
2.6 KiB
JavaScript
90 lines
2.6 KiB
JavaScript
/**
|
||
* 扫描前端 hasPermission / 路由 permission,输出三级按钮收集结果
|
||
* 用法: node scripts/collect-page-buttons.mjs
|
||
*/
|
||
import fs from 'fs';
|
||
import path from 'path';
|
||
import { fileURLToPath } from 'url';
|
||
|
||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||
const root = path.resolve(__dirname, '..');
|
||
const srcDir = path.join(root, 'src');
|
||
|
||
const ACTION_LABELS = {
|
||
Query: '查询',
|
||
Create: '新增',
|
||
Update: '修改',
|
||
Delete: '删除',
|
||
Move: '移动',
|
||
AssignRoles: '分配角色',
|
||
AssignPermissions: '分配权限',
|
||
ResetPassword: '重置密码',
|
||
Template: '模板管理',
|
||
Audit: '审计',
|
||
Use: '使用',
|
||
Save: '保存',
|
||
Export: '导出',
|
||
Import: '导入',
|
||
};
|
||
|
||
function walk(dir, ext, out = []) {
|
||
for (const name of fs.readdirSync(dir)) {
|
||
const full = path.join(dir, name);
|
||
const stat = fs.statSync(full);
|
||
if (stat.isDirectory()) {
|
||
if (name === 'node_modules') continue;
|
||
walk(full, ext, out);
|
||
} else if (full.endsWith(ext)) {
|
||
out.push(full);
|
||
}
|
||
}
|
||
return out;
|
||
}
|
||
|
||
function inferParent(code) {
|
||
const parts = code.split('.');
|
||
if (parts.length < 3) return null;
|
||
// 资源级:Rbac.Menus.Create → Rbac.Menus
|
||
return `${parts[0]}.${parts[1]}`;
|
||
}
|
||
|
||
function inferName(code) {
|
||
const action = code.split('.').pop();
|
||
return ACTION_LABELS[action] || action;
|
||
}
|
||
|
||
const vueFiles = walk(path.join(srcDir, 'views'), '.vue');
|
||
const routeFiles = walk(path.join(srcDir, 'router'), '.ts');
|
||
|
||
const permissionCodes = new Set();
|
||
|
||
for (const file of [...vueFiles, ...routeFiles]) {
|
||
const text = fs.readFileSync(file, 'utf8');
|
||
const hasPermissionRe = /hasPermission\(\s*['"]([^'"]+)['"]\s*\)/g;
|
||
const routePermRe = /permission:\s*['"]([^'"]+)['"]/g;
|
||
let m;
|
||
while ((m = hasPermissionRe.exec(text))) permissionCodes.add(m[1]);
|
||
while ((m = routePermRe.exec(text))) permissionCodes.add(m[1]);
|
||
}
|
||
|
||
const grouped = new Map();
|
||
for (const code of [...permissionCodes].sort()) {
|
||
const parent = inferParent(code);
|
||
if (!parent || parent === code) continue;
|
||
if (!grouped.has(parent)) grouped.set(parent, []);
|
||
grouped.get(parent).push({ permissionCode: code, name: inferName(code) });
|
||
}
|
||
|
||
console.log('# 前端页面按钮收集结果\n');
|
||
console.log(`扫描文件: ${vueFiles.length} 个 vue, ${routeFiles.length} 个路由`);
|
||
console.log(`权限码总数: ${permissionCodes.size}`);
|
||
console.log(`可分组三级按钮父级: ${grouped.size}\n`);
|
||
|
||
for (const [parent, buttons] of [...grouped.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
|
||
console.log(`## ${parent}`);
|
||
buttons.forEach((btn, idx) => {
|
||
console.log(` ${idx + 1}. ${btn.permissionCode} → ${btn.name}`);
|
||
});
|
||
console.log('');
|
||
}
|