refactor(pages.json&scripts): 优化自定义组件占位符注入逻辑
1. 为商品详情页添加所有diy-*组件的占位符配置 2. 重构占位符注入脚本,实现组件使用的递归检测 3. 移除原有的简单字符串匹配,改用导入链追踪准确判断组件使用情况
This commit is contained in:
58
pages.json
58
pages.json
@@ -218,7 +218,63 @@
|
||||
{
|
||||
"path": "detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "商品详情"
|
||||
"navigationBarTitleText": "商品详情",
|
||||
"componentPlaceholder": {
|
||||
"diy-article": "view",
|
||||
"diy-audio": "view",
|
||||
"diy-bargain": "view",
|
||||
"diy-bottom-nav": "view",
|
||||
"diy-category": "view",
|
||||
"diy-category-item": "view",
|
||||
"diy-channel-list": "view",
|
||||
"diy-channel-video": "view",
|
||||
"diy-comp-extend": "view",
|
||||
"diy-coupon": "view",
|
||||
"diy-digit": "view",
|
||||
"diy-fenxiao-goods-list": "view",
|
||||
"diy-float-btn": "view",
|
||||
"diy-follow-official-account": "view",
|
||||
"diy-form": "view",
|
||||
"diy-goods-brand": "view",
|
||||
"diy-goods-list": "view",
|
||||
"diy-goods-recommend": "view",
|
||||
"diy-graphic-nav": "view",
|
||||
"diy-group": "view",
|
||||
"diy-groupbuy": "view",
|
||||
"diy-horz-blank": "view",
|
||||
"diy-horz-line": "view",
|
||||
"diy-hot-area": "view",
|
||||
"diy-icon": "view",
|
||||
"diy-image-nav": "view",
|
||||
"diy-img-ads": "view",
|
||||
"diy-index-page": "view",
|
||||
"diy-kefu": "view",
|
||||
"diy-listmenu": "view",
|
||||
"diy-live": "view",
|
||||
"diy-many-goods-list": "view",
|
||||
"diy-map": "view",
|
||||
"diy-member-info": "view",
|
||||
"diy-member-my-order": "view",
|
||||
"diy-merch-list": "view",
|
||||
"diy-notes": "view",
|
||||
"diy-notice": "view",
|
||||
"diy-payment-qrcode": "view",
|
||||
"diy-picture": "view",
|
||||
"diy-pinfan": "view",
|
||||
"diy-pintuan": "view",
|
||||
"diy-presale": "view",
|
||||
"diy-quick-nav": "view",
|
||||
"diy-rich-text": "view",
|
||||
"diy-rubik-cube": "view",
|
||||
"diy-search": "view",
|
||||
"diy-seckill": "view",
|
||||
"diy-store": "view",
|
||||
"diy-store-label": "view",
|
||||
"diy-tab": "view",
|
||||
"diy-text": "view",
|
||||
"diy-video": "view",
|
||||
"diy-video-list": "view"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user