diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..50494d58 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +fe/example/**/dd编译/ + + diff --git a/fe/README.md b/fe/README.md index 3a3bbfee..ad4baaca 100644 --- a/fe/README.md +++ b/fe/README.md @@ -54,6 +54,9 @@ pnpm test # 注意:需要 shared/jsapp 目录存在 pnpm generate:app +# 兼容windows环境生成小程序到shared/jsapp +pnpm generate:app1 + # 生成SDK包 # 注意:需要先执行构建命令 pnpm generate:sdk diff --git a/fe/package.json b/fe/package.json index 95fef490..ce382474 100644 --- a/fe/package.json +++ b/fe/package.json @@ -8,6 +8,11 @@ "pnpm": ">=7" }, "scripts": { + "generate:app1": "node ./scripts/generate-app1.js", + + + + "build:dev": "pnpm --filter container... build --mode development", "build": "pnpm --filter container... build --mode production", "compile": "node ./packages/compiler/src/bin/compile.js", diff --git a/fe/scripts/generate-app1.js b/fe/scripts/generate-app1.js new file mode 100644 index 00000000..133cc0a9 --- /dev/null +++ b/fe/scripts/generate-app1.js @@ -0,0 +1,259 @@ +#!/usr/bin/env node + +const { execSync } = require('node:child_process') +const fs = require('node:fs') +const path = require('node:path') +const process = require('node:process') + +// ===================== 依赖检查 ===================== +function checkAndInstallArchiver() { + try { + require.resolve('archiver'); + console.log('✅ archiver 依赖已安装'); + } catch (err) { + console.log(`⚠️ 正在安装 archiver...`); + try { + execSync('pnpm install archiver --save-dev', { stdio: 'inherit', cwd: path.resolve(__dirname, '../') }); + } catch (installErr) { + console.error(`❌ archiver 安装失败,请手动执行:pnpm install archiver --save-dev`); + process.exit(1); + } + } +} +checkAndInstallArchiver(); +const archiver = require('archiver'); + +// ===================== 工具函数 ===================== +/** + * 安全读取配置 + */ +function safeReadConfig(configPath) { + try { + if (!fs.existsSync(configPath)) { + console.warn(`⚠️ 配置文件不存在:${configPath}`); + return { appid: `unknown_${path.basename(path.dirname(configPath))}` }; // 兜底appid + } + const content = fs.readFileSync(configPath, 'utf8'); + const config = JSON.parse(content); + if (!config.appid) { + console.warn(`⚠️ 配置文件无appid:${configPath},使用兜底appid`); + config.appid = `unknown_${path.basename(path.dirname(configPath))}`; + } + return config; + } catch (err) { + console.error(`❌ 读取配置失败:${err.message},使用兜底appid`); + return { appid: `unknown_${path.basename(path.dirname(configPath))}` }; + } +} + +/** + * 压缩目录(保留main目录结构) + 详细调试日志 + */ +async function zipDirectory(sourceDir, outputZipPath) { + const mainDir = path.join(sourceDir, 'main'); + console.log(`[调试] 待压缩的main文件夹:${mainDir}`); + console.log(`[调试] 压缩目标路径:${outputZipPath}`); + + if (!fs.existsSync(mainDir)) { + console.error(`❌ 压缩失败:main文件夹不存在 ${mainDir}`); + return false; + } + const files = fs.readdirSync(mainDir); + if (files.length === 0) { + console.error(`❌ 压缩失败:main文件夹为空 ${mainDir}`); + return false; + } + + return new Promise((resolve) => { + try { + const zipParentDir = path.dirname(outputZipPath); + if (!fs.existsSync(zipParentDir)) { + fs.mkdirSync(zipParentDir, { recursive: true }); + console.log(`[调试] 创建目标目录:${zipParentDir}`); + } + + const output = fs.createWriteStream(outputZipPath); + const archive = archiver('zip', { zlib: { level: 9 } }); + + output.on('close', () => { + console.log(`✅ 压缩完成,ZIP大小:${(archive.pointer() / 1024).toFixed(2)} KB`); + resolve(true); + }); + + archive.on('error', (err) => { + console.error(`❌ 压缩异常:${err.message}`); + resolve(false); + }); + + archive.pipe(output); + // 核心修正:显式指定ZIP内的目录名为'main',消除冗余路径 + archive.directory(mainDir, 'main'); + archive.finalize(); + } catch (err) { + console.error(`❌ 压缩初始化失败:${err.message}`); + resolve(false); + } + }); + } +/** + * 创建/更新config.json(压缩成功后执行) + * @param {string} configPath config.json文件路径 + * @param {string} appId 小程序appid + */ +function updateConfigJson(configPath, appId,小程序名称,小程序版本) { + try { + // 1. 初始化默认配置 + let config = { + "appId": appId, + "name": 小程序名称?小程序名称:"小程序", + "path": "example/index", + "versionCode": 1, + "versionName": 小程序版本?小程序版本:"1.0.0" + }; + + // 2. 如果文件存在,读取并递增版本号 + if (fs.existsSync(configPath)) { + const content = fs.readFileSync(configPath, 'utf8'); + const existingConfig = JSON.parse(content); + // 保留原有name/path(如果有),仅更新appId、递增版本号 + config = { + ...existingConfig, + appId: appId, // 确保appId正确更新 + name: 小程序名称?小程序名称:"小程序", // 确保name正确更新 + versionCode: (existingConfig.versionCode || 1) + 1, // 递增versionCode + }; + // 递增versionName最后一位(如1.0.1 → 1.0.2) + const versionParts = (config.versionName || "1.0.0").split('.'); + versionParts[versionParts.length - 1] = (Number.parseInt(versionParts[versionParts.length - 1]) + 1).toString(); + config.versionName = versionParts.join('.'); + console.log(`[调试] 读取原有config.json,versionCode递增为:${config.versionCode}`); + } else { + console.log(`[调试] config.json不存在,创建新文件并初始化版本号`); + } + + // 3. 写入config.json(格式化输出,便于阅读) + fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); + console.log(`✅ config.json更新成功:${configPath}`); + console.log(`[调试] 最新配置:`, config); + } catch (err) { + console.error(`❌ 更新config.json失败:${err.message}`); + } +} + +/** + * 复制config.json到压缩包同级目录(覆盖已有文件) + * @param {string} sourceConfigPath 源config.json路径(产物目录下) + * @param {string} targetDir 目标目录(压缩包所在目录) + */ +function copyConfigToZipDir(sourceConfigPath, targetDir) { + try { + // 1. 检查源config.json是否存在 + if (!fs.existsSync(sourceConfigPath)) { + console.error(`❌ 复制失败:源config.json不存在 ${sourceConfigPath}`); + return false; + } + + // 2. 拼接目标config.json路径(压缩包同目录,仅为config.json) + const targetConfigPath = path.join(targetDir, 'config.json'); + // 确保目标目录存在 + if (!fs.existsSync(targetDir)) { + fs.mkdirSync(targetDir, { recursive: true }); + console.log(`[调试] 创建目标配置目录:${targetDir}`); + } + + // 3. 复制文件(覆盖已有文件,fs.copyFileSync默认覆盖) + fs.copyFileSync(sourceConfigPath, targetConfigPath); + console.log(`✅ config.json复制成功:${sourceConfigPath} → ${targetConfigPath}`); + return true; + } catch (err) { + console.error(`❌ 复制config.json失败:${err.message}`); + return false; + } +} + +// ===================== 配置项 ===================== +const 小程序打包路径 = path.resolve(__dirname, '../../shared/jsapp'); +const 小程序实例路径 = path.resolve(__dirname, '../example'); +const 编译目录 = 'dd编译'; +const 编译命令 = `dmcc build -s ./${编译目录}`; +const 小程序配置文件名称 = 'project.config.json'; + +// ===================== 前置检查 ===================== +if (!fs.existsSync(小程序打包路径)) { + console.error(`错误:打包目录不存在 ${小程序打包路径}`); + process.exit(1); +} +if (!fs.existsSync(小程序实例路径)) { + console.error(`错误:小程序实例目录不存在 ${小程序实例路径}`); + process.exit(1); +} + +// ===================== 主流程 ===================== +async function main() { + console.log(`===== 开始处理(调试模式)=====`); + console.log(`编译命令:${编译命令}`); + + // 1. 获取小程序目录列表 + const 小程序目录列表 = fs.readdirSync(小程序实例路径) + .filter(item => fs.statSync(path.join(小程序实例路径, item)).isDirectory()); + + if (小程序目录列表.length === 0) { + console.log(`⚠️ 无小程序目录`); + return; + } + + // 2. 编译所有小程序 + for (const 小程序目录名 of 小程序目录列表) { + const 小程序完整路径 = path.join(小程序实例路径, 小程序目录名); + console.log(`\n--- 编译【${小程序目录名}】---`); + try { + execSync(编译命令, { cwd: 小程序完整路径, stdio: 'inherit' }); + console.log(`✅ 编译成功`); + } catch (err) { + console.error(`❌ 编译失败:${err.message}`); + } + } + + // 3. 压缩所有产物 + 更新+复制config.json + console.log(`\n--- 开始压缩所有产物(保留main目录结构)---`); + for (const 小程序目录名 of 小程序目录列表) { + const 小程序完整路径 = path.join(小程序实例路径, 小程序目录名); + const 配置文件路径 = path.join(小程序完整路径, 小程序配置文件名称); + + console.log(`\n处理【${小程序目录名}】`); + // 读取配置(带兜底) + const 小程序配置 = safeReadConfig(配置文件路径); + const 小程序appid = 小程序配置.appid; + const 小程序名称 = 小程序配置.projectname; + const 小程序版本 = 小程序配置.libVersion; + console.log(`[调试] appid:${小程序appid}`); + + const 小程序产物目录 = path.join(小程序完整路径, 编译目录, 小程序appid); + // 拼接压缩路径 + const zipOutputPath = path.join(小程序打包路径, 小程序appid, `${小程序appid}.zip`); + // 压缩包所在目录(用于复制config.json) + const zipDir = path.dirname(zipOutputPath); + // 执行压缩(保留main目录结构) + const 压缩成功 = await zipDirectory(小程序产物目录, zipOutputPath); + + if (压缩成功) { + console.log(`✅ 【${小程序目录名}】压缩完成,ZIP路径:${zipOutputPath}`); + // 步骤1:更新/创建产物目录下的config.json + const localConfigPath = path.join(小程序产物目录, 'config.json'); + updateConfigJson(localConfigPath, 小程序appid,小程序名称,小程序版本); + + // 步骤2:复制config.json到压缩包同级目录(仅为config.json,覆盖已有) + copyConfigToZipDir(localConfigPath, zipDir); + } else { + console.error(`❌ 【${小程序目录名}】压缩失败,跳过config.json更新/复制`); + } + } + + console.log(`\n===== 所有流程结束 =====`); +} + +// 执行主流程 +main().catch(err => { + console.error(`❌ 脚本异常:${err.message}`); + process.exit(1); +}); \ No newline at end of file diff --git a/shared/jsapp/wx92269e3b2f304afc/config.json b/shared/jsapp/wx92269e3b2f304afc/config.json index 377401c1..6f137743 100644 --- a/shared/jsapp/wx92269e3b2f304afc/config.json +++ b/shared/jsapp/wx92269e3b2f304afc/config.json @@ -1,7 +1,7 @@ { "appId": "wx92269e3b2f304afc", - "name": "WeUI for 小程序", "path": "example/index", - "versionCode": 2, - "versionName": "1.0.1" + "versionCode": 5, + "versionName": "1.0.4", + "name": "WeUI for 小程序" } \ No newline at end of file diff --git a/shared/jsapp/wx92269e3b2f304afc/wx92269e3b2f304afc.zip b/shared/jsapp/wx92269e3b2f304afc/wx92269e3b2f304afc.zip index 15e1ec6d..4231d543 100644 Binary files a/shared/jsapp/wx92269e3b2f304afc/wx92269e3b2f304afc.zip and b/shared/jsapp/wx92269e3b2f304afc/wx92269e3b2f304afc.zip differ diff --git a/shared/jsapp/wxe5f52902cf4de896/config.json b/shared/jsapp/wxe5f52902cf4de896/config.json index 7f8a443a..facd9b2e 100644 --- a/shared/jsapp/wxe5f52902cf4de896/config.json +++ b/shared/jsapp/wxe5f52902cf4de896/config.json @@ -1,7 +1,7 @@ { "appId": "wxe5f52902cf4de896", - "name": "小程序官方组件展示", - "path": "page/tabBar/component/index", - "versionCode": 2, - "versionName": "1.0.1" + "path": "example/index", + "versionCode": 5, + "versionName": "1.0.4", + "name": "demo-subpackages.b42a3adb" } \ No newline at end of file diff --git a/shared/jsapp/wxe5f52902cf4de896/wxe5f52902cf4de896.zip b/shared/jsapp/wxe5f52902cf4de896/wxe5f52902cf4de896.zip index c05d2e34..74032320 100644 Binary files a/shared/jsapp/wxe5f52902cf4de896/wxe5f52902cf4de896.zip and b/shared/jsapp/wxe5f52902cf4de896/wxe5f52902cf4de896.zip differ