完成consumer端同步
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* 切换 pages.json 在「完整模式」和「商家端专属模式」之间
|
||||
* 切换 pages.json 到不同端的专属编译模式。
|
||||
*
|
||||
* 用法:
|
||||
* npm run pages:merchant → 仅编译 merchant 相关页面(大幅缩短编译时间)
|
||||
* npm run pages:consumer → 仅编译 consumer 相关页面
|
||||
* npm run pages:merchant → 仅编译 merchant 相关页面
|
||||
* npm run pages:admin → 仅编译 admin 相关页面
|
||||
* npm run pages:full → 恢复完整 pages.json
|
||||
*/
|
||||
const fs = require("fs");
|
||||
@@ -11,35 +13,415 @@ const path = require("path");
|
||||
const root = path.resolve(__dirname, "..");
|
||||
const pagesJson = path.join(root, "pages.json");
|
||||
const pagesFull = path.join(root, "pages.full.json");
|
||||
const pagesMerchant = path.join(root, "pages.merchant.json");
|
||||
const backupDir = path.join(root, ".pages-backup");
|
||||
const pageExtensions = [".uvue", ".vue", ".nvue"];
|
||||
|
||||
const mode = process.argv[2]; // 'merchant' | 'full'
|
||||
const consumerUserPages = [
|
||||
"pages/user/boot",
|
||||
"pages/user/login",
|
||||
"pages/user/register",
|
||||
"pages/user/forgot-password",
|
||||
"pages/user/terms",
|
||||
"pages/user/center",
|
||||
"pages/user/profile",
|
||||
"pages/user/change-password",
|
||||
"pages/user/bind-phone",
|
||||
"pages/user/bind-email",
|
||||
];
|
||||
|
||||
if (mode === "merchant") {
|
||||
if (!fs.existsSync(pagesMerchant)) {
|
||||
console.error("❌ pages.merchant.json 不存在,请先创建该文件。");
|
||||
const merchantUserPages = [
|
||||
"pages/user/login",
|
||||
"pages/user/boot",
|
||||
"pages/user/register",
|
||||
"pages/user/forgot-password",
|
||||
"pages/user/terms",
|
||||
"pages/user/change-password",
|
||||
];
|
||||
|
||||
const adminUserPages = [
|
||||
"pages/user/login",
|
||||
"pages/user/boot",
|
||||
"pages/user/forgot-password",
|
||||
"pages/user/terms",
|
||||
"pages/user/change-password",
|
||||
];
|
||||
|
||||
const targetConfigs = {
|
||||
consumer: {
|
||||
fileName: "pages.consumer.json",
|
||||
label: "消费者端",
|
||||
entryPath: "pages/main/index",
|
||||
orderedTopLevelPaths: [
|
||||
"pages/main/index",
|
||||
...consumerUserPages,
|
||||
"pages/main/category",
|
||||
"pages/main/messages",
|
||||
"pages/main/cart",
|
||||
"pages/main/profile",
|
||||
],
|
||||
topLevelMatcher(pagePath) {
|
||||
return (
|
||||
pagePath.startsWith("pages/main/") ||
|
||||
consumerUserPages.includes(pagePath)
|
||||
);
|
||||
},
|
||||
subPackageMatcher(rootPath) {
|
||||
return rootPath === "pages/mall/consumer";
|
||||
},
|
||||
tabBarMatcher(pagePath) {
|
||||
return pagePath.startsWith("pages/main/");
|
||||
},
|
||||
defaultCondition() {
|
||||
return {
|
||||
current: 0,
|
||||
list: [
|
||||
{
|
||||
name: "consumer端",
|
||||
path: "pages/main/index",
|
||||
query: "role=consumer",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
merchant: {
|
||||
fileName: "pages.merchant.json",
|
||||
label: "商家端",
|
||||
entryPath: "pages/user/login",
|
||||
orderedTopLevelPaths: [
|
||||
"pages/user/login",
|
||||
"pages/user/boot",
|
||||
"pages/user/register",
|
||||
"pages/user/forgot-password",
|
||||
"pages/user/terms",
|
||||
"pages/user/change-password",
|
||||
"pages/mall/merchant/index",
|
||||
"pages/mall/merchant/messages",
|
||||
"pages/mall/merchant/orders",
|
||||
"pages/mall/merchant/growth",
|
||||
"pages/mall/merchant/profile",
|
||||
],
|
||||
topLevelMatcher(pagePath) {
|
||||
return (
|
||||
merchantUserPages.includes(pagePath) ||
|
||||
pagePath.startsWith("pages/mall/merchant/")
|
||||
);
|
||||
},
|
||||
subPackageMatcher() {
|
||||
return false;
|
||||
},
|
||||
defaultCondition() {
|
||||
return {
|
||||
current: 0,
|
||||
list: [
|
||||
{
|
||||
name: "merchant端",
|
||||
path: "pages/mall/merchant/index",
|
||||
query: "role=merchant",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
admin: {
|
||||
fileName: "pages.admin.json",
|
||||
label: "管理后台",
|
||||
entryPath: "pages/user/login",
|
||||
orderedTopLevelPaths: [
|
||||
"pages/user/login",
|
||||
"pages/user/boot",
|
||||
"pages/user/forgot-password",
|
||||
"pages/user/terms",
|
||||
"pages/user/change-password",
|
||||
"pages/mall/admin/homePage/index",
|
||||
"pages/mall/admin/userCenter/index",
|
||||
],
|
||||
topLevelMatcher(pagePath) {
|
||||
return (
|
||||
adminUserPages.includes(pagePath) ||
|
||||
pagePath === "pages/mall/admin/homePage/index" ||
|
||||
pagePath === "pages/mall/admin/userCenter/index"
|
||||
);
|
||||
},
|
||||
subPackageMatcher(rootPath) {
|
||||
return rootPath.startsWith("pages/mall/admin/");
|
||||
},
|
||||
defaultCondition() {
|
||||
return {
|
||||
current: 0,
|
||||
list: [
|
||||
{
|
||||
name: "admin端",
|
||||
path: "pages/mall/admin/homePage/index",
|
||||
query: "role=admin",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mode = process.argv[2]; // 'consumer' | 'merchant' | 'admin' | 'full'
|
||||
|
||||
function readJson(filePath) {
|
||||
const rawContent = fs.readFileSync(filePath, "utf8").replace(/^\uFEFF/, "");
|
||||
return JSON.parse(rawContent);
|
||||
}
|
||||
|
||||
function writeJson(filePath, content) {
|
||||
fs.writeFileSync(filePath, `${JSON.stringify(content, null, 2)}\n`, "utf8");
|
||||
}
|
||||
|
||||
function ensureFullBackup() {
|
||||
if (fs.existsSync(pagesFull)) {
|
||||
return;
|
||||
}
|
||||
fs.copyFileSync(pagesJson, pagesFull);
|
||||
console.log("📦 已备份 pages.json → pages.full.json");
|
||||
}
|
||||
|
||||
function backupCurrentPages(targetName) {
|
||||
if (!fs.existsSync(pagesJson)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.mkdirSync(backupDir, { recursive: true });
|
||||
const timestamp = new Date().toISOString().replace(/[.:]/g, "-");
|
||||
const backupPath = path.join(
|
||||
backupDir,
|
||||
`pages.${targetName}.${timestamp}.json`,
|
||||
);
|
||||
fs.copyFileSync(pagesJson, backupPath);
|
||||
console.log(`📦 已备份当前 pages.json → ${path.relative(root, backupPath)}`);
|
||||
}
|
||||
|
||||
function getPageMap(fullConfig) {
|
||||
return new Map(fullConfig.pages.map((page) => [page.path, page]));
|
||||
}
|
||||
|
||||
function findMatchingPageFile(routePath) {
|
||||
for (const extension of pageExtensions) {
|
||||
const candidate = path.join(root, `${routePath}${extension}`);
|
||||
if (fs.existsSync(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function clonePage(page) {
|
||||
return JSON.parse(JSON.stringify(page));
|
||||
}
|
||||
|
||||
function flattenSubPackagePages(fullConfig, rootPath) {
|
||||
const targetPackage = fullConfig.subPackages.find(
|
||||
(item) => item.root === rootPath,
|
||||
);
|
||||
if (!targetPackage) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return targetPackage.pages.map((page) => ({
|
||||
path: `${rootPath}/${page.path}`,
|
||||
style: page.style ? JSON.parse(JSON.stringify(page.style)) : {},
|
||||
}));
|
||||
}
|
||||
|
||||
function getTopLevelPages(fullConfig, targetConfig) {
|
||||
const pageMap = getPageMap(fullConfig);
|
||||
const matchedFromTopLevel = fullConfig.pages
|
||||
.filter((page) => targetConfig.topLevelMatcher(page.path))
|
||||
.map((page) => clonePage(page));
|
||||
|
||||
const flattenedPages = (targetConfig.flattenRoots || []).flatMap((rootPath) =>
|
||||
flattenSubPackagePages(fullConfig, rootPath),
|
||||
);
|
||||
|
||||
const mergedMap = new Map();
|
||||
for (const page of [...matchedFromTopLevel, ...flattenedPages]) {
|
||||
mergedMap.set(page.path, page);
|
||||
}
|
||||
|
||||
const orderedPages = [];
|
||||
for (const pagePath of targetConfig.orderedTopLevelPaths) {
|
||||
if (mergedMap.has(pagePath)) {
|
||||
orderedPages.push(mergedMap.get(pagePath));
|
||||
mergedMap.delete(pagePath);
|
||||
} else if (pageMap.has(pagePath)) {
|
||||
orderedPages.push(clonePage(pageMap.get(pagePath)));
|
||||
}
|
||||
}
|
||||
|
||||
for (const page of [...matchedFromTopLevel, ...flattenedPages]) {
|
||||
if (mergedMap.has(page.path)) {
|
||||
orderedPages.push(mergedMap.get(page.path));
|
||||
mergedMap.delete(page.path);
|
||||
}
|
||||
}
|
||||
|
||||
return dedupePages(orderedPages);
|
||||
}
|
||||
|
||||
function getSubPackages(fullConfig, targetConfig) {
|
||||
return fullConfig.subPackages
|
||||
.filter((item) => targetConfig.subPackageMatcher(item.root))
|
||||
.map((item) => JSON.parse(JSON.stringify(item)));
|
||||
}
|
||||
|
||||
function dedupePages(pages) {
|
||||
const seen = new Set();
|
||||
return pages.filter((page) => {
|
||||
if (seen.has(page.path)) {
|
||||
return false;
|
||||
}
|
||||
seen.add(page.path);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function getCondition(targetConfig, sourceCondition) {
|
||||
if (sourceCondition && Array.isArray(sourceCondition.list)) {
|
||||
const filteredList = sourceCondition.list.filter(
|
||||
(item) => item.path === targetConfig.entryPath,
|
||||
);
|
||||
if (filteredList.length > 0) {
|
||||
return {
|
||||
current: 0,
|
||||
list: filteredList,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return targetConfig.defaultCondition();
|
||||
}
|
||||
|
||||
function validateGeneratedConfig(targetName, config) {
|
||||
const missingRoutes = [];
|
||||
const routeSet = new Set();
|
||||
|
||||
for (const page of config.pages || []) {
|
||||
routeSet.add(page.path);
|
||||
if (!findMatchingPageFile(page.path)) {
|
||||
missingRoutes.push(page.path);
|
||||
}
|
||||
}
|
||||
|
||||
for (const subPackage of config.subPackages || []) {
|
||||
for (const page of subPackage.pages || []) {
|
||||
const fullPath = `${subPackage.root}/${page.path}`;
|
||||
routeSet.add(fullPath);
|
||||
if (!findMatchingPageFile(fullPath)) {
|
||||
missingRoutes.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const tabItem of config.tabBar?.list || []) {
|
||||
if (!routeSet.has(tabItem.pagePath)) {
|
||||
missingRoutes.push(`tabBar -> ${tabItem.pagePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const conditionItem of config.condition?.list || []) {
|
||||
if (!routeSet.has(conditionItem.path)) {
|
||||
missingRoutes.push(`condition -> ${conditionItem.path}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingRoutes.length > 0) {
|
||||
console.error(`❌ ${targetName} 配置存在无效页面引用:`);
|
||||
for (const routePath of missingRoutes) {
|
||||
console.error(` - ${routePath}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
// 备份当前 pages.json(仅在未备份时执行,避免覆盖真正的完整版本)
|
||||
if (!fs.existsSync(pagesFull)) {
|
||||
fs.copyFileSync(pagesJson, pagesFull);
|
||||
console.log("📦 已备份 pages.json → pages.full.json");
|
||||
}
|
||||
|
||||
function buildTargetConfig(fullConfig, targetName, sourceCondition) {
|
||||
const targetConfig = targetConfigs[targetName];
|
||||
const nextConfig = {};
|
||||
|
||||
nextConfig.pages = getTopLevelPages(fullConfig, targetConfig);
|
||||
nextConfig.subPackages = getSubPackages(fullConfig, targetConfig);
|
||||
|
||||
if (targetConfig.tabBarMatcher) {
|
||||
const filteredTabBarList = (fullConfig.tabBar?.list || []).filter((item) =>
|
||||
targetConfig.tabBarMatcher(item.pagePath),
|
||||
);
|
||||
if (filteredTabBarList.length > 0 && fullConfig.tabBar) {
|
||||
nextConfig.tabBar = {
|
||||
...JSON.parse(JSON.stringify(fullConfig.tabBar)),
|
||||
list: filteredTabBarList,
|
||||
};
|
||||
}
|
||||
}
|
||||
fs.copyFileSync(pagesMerchant, pagesJson);
|
||||
console.log("✅ 已切换为【商家端专属编译模式】");
|
||||
console.log(" 仅包含 merchant 页面,差量编译速度大幅提升。");
|
||||
|
||||
for (const key of Object.keys(fullConfig)) {
|
||||
if (["pages", "subPackages", "tabBar", "condition"].includes(key)) {
|
||||
continue;
|
||||
}
|
||||
nextConfig[key] = JSON.parse(JSON.stringify(fullConfig[key]));
|
||||
}
|
||||
|
||||
nextConfig.condition = getCondition(targetConfig, sourceCondition);
|
||||
|
||||
validateGeneratedConfig(targetName, nextConfig);
|
||||
return nextConfig;
|
||||
}
|
||||
|
||||
function writeTargetConfig(targetName, config) {
|
||||
const targetPath = path.join(root, targetConfigs[targetName].fileName);
|
||||
writeJson(targetPath, config);
|
||||
fs.copyFileSync(targetPath, pagesJson);
|
||||
|
||||
const pageCount = config.pages.length;
|
||||
const subPackageCount = config.subPackages.length;
|
||||
const tabBarCount = config.tabBar?.list?.length || 0;
|
||||
|
||||
console.log(`✅ 已切换为【${targetConfigs[targetName].label}专属编译模式】`);
|
||||
console.log(` 目标配置:${targetConfigs[targetName].fileName}`);
|
||||
console.log(` pages:${pageCount} 个`);
|
||||
console.log(` subPackages:${subPackageCount} 个`);
|
||||
console.log(` tabBar:${tabBarCount} 个`);
|
||||
console.log(" 恢复完整版本:npm run pages:full");
|
||||
} else if (mode === "full") {
|
||||
}
|
||||
|
||||
function restoreFullPages() {
|
||||
if (!fs.existsSync(pagesFull)) {
|
||||
console.error("❌ pages.full.json 不存在。");
|
||||
console.error(" 可能当前已经是完整模式,或备份文件已被删除。");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
backupCurrentPages("full");
|
||||
fs.copyFileSync(pagesFull, pagesJson);
|
||||
console.log("✅ 已恢复【完整 pages.json】");
|
||||
console.log(" 包含 consumer + merchant + admin 全部页面。");
|
||||
}
|
||||
|
||||
if (mode === "full") {
|
||||
restoreFullPages();
|
||||
} else if (Object.prototype.hasOwnProperty.call(targetConfigs, mode)) {
|
||||
ensureFullBackup();
|
||||
backupCurrentPages(mode);
|
||||
|
||||
const fullConfig = readJson(pagesFull);
|
||||
const sourceCondition = fs.existsSync(pagesJson)
|
||||
? (() => {
|
||||
try {
|
||||
return readJson(pagesJson).condition;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
})()
|
||||
: null;
|
||||
|
||||
const nextConfig = buildTargetConfig(fullConfig, mode, sourceCondition);
|
||||
writeTargetConfig(mode, nextConfig);
|
||||
} else {
|
||||
console.log("用法:");
|
||||
console.log(" npm run pages:consumer 切换到消费者端专属编译模式");
|
||||
console.log(" npm run pages:merchant 切换到商家端专属编译模式");
|
||||
console.log(" npm run pages:admin 切换到管理后台专属编译模式");
|
||||
console.log(" npm run pages:full 恢复完整编译模式");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user