refactor(pages.json&scripts): 优化自定义组件占位符注入逻辑

1.  为商品详情页添加所有diy-*组件的占位符配置
2.  重构占位符注入脚本,实现组件使用的递归检测
3.  移除原有的简单字符串匹配,改用导入链追踪准确判断组件使用情况
This commit is contained in:
2026-07-10 17:45:38 +08:00
parent 81e85c804a
commit 575145eae9
2 changed files with 118 additions and 11 deletions

View File

@@ -99,18 +99,69 @@ function lastMeaningfulIdx(bodyLines) {
}
/**
* 检查 page 的 .vue 文件是否引用了 <diy-*> 组件.
* 简单的字符串检查, 包含 <diy- 即认为使用 (覆盖模板引用、动态组件等).
* 把 import specifier 解析为相对项目根的 .vue 路径(不带扩展名).
* 仅处理 ./ ../ @/ 开头的本地路径; node_modules 等外部模块直接返回 null.
*/
function resolveVueImport(fromRel, spec) {
let abs;
if (spec.startsWith('@/')) {
abs = path.join(PROJECT_ROOT, spec.slice(2));
} else if (spec.startsWith('./') || spec.startsWith('../')) {
abs = path.resolve(path.dirname(path.join(PROJECT_ROOT, fromRel + '.vue')), spec);
} else {
return null;
}
let rel = path.relative(PROJECT_ROOT, abs).replace(/\\/g, '/');
if (rel.startsWith('..')) return null;
if (!rel.endsWith('.vue')) return null;
return rel.slice(0, -'.vue'.length);
}
/**
* 缓存: 相对路径 → 是否(直接或传递)使用了 <diy-*>.
*/
const _usesDiyCache = new Map();
const _importRe = /import\s+[^'"`;\n]*['"]([^'"`]+\.vue)['"]/g;
/**
* 检查一个 .vue 文件是否(传递)使用了 <diy-*> 组件.
* 不仅看模板里是否含 <diy-, 还会沿 import 链继续追踪子组件.
* 例如 pages_goods/detail.vue → _components/goods-detail-view/goods-detail-view.vue → <diy-icon>
*/
function fileUsesDiy(relVuePath) {
if (!relVuePath) return false;
if (_usesDiyCache.has(relVuePath)) return _usesDiyCache.get(relVuePath);
// 暂存 false 以打破循环引用
_usesDiyCache.set(relVuePath, false);
const abs = path.join(PROJECT_ROOT, relVuePath + '.vue');
let content;
try {
content = fs.readFileSync(abs, 'utf-8');
} catch (e) {
return false;
}
if (/<diy-/.test(content)) {
_usesDiyCache.set(relVuePath, true);
return true;
}
_importRe.lastIndex = 0;
let m;
while ((m = _importRe.exec(content)) !== null) {
const target = resolveVueImport(relVuePath, m[1]);
if (target && fileUsesDiy(target)) {
_usesDiyCache.set(relVuePath, true);
return true;
}
}
return false;
}
/**
* 检查 page 的 .vue 文件(或其传递子组件)是否引用了 <diy-*> 组件.
* fullPagePath 是 pages.json 中拼接的页面路径, 如 "pages_goods/detail".
*/
function pageUsesDiy(fullPagePath) {
if (!fullPagePath) return false;
const vuePath = path.join(PROJECT_ROOT, fullPagePath + '.vue');
try {
const content = fs.readFileSync(vuePath, 'utf-8');
return /<diy-/.test(content);
} catch (e) {
return false; // 文件不存在时不注入
}
return fileUsesDiy(fullPagePath);
}
/**