| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- const ci = require('miniprogram-ci')
- const path = require('path')
- const { execSync } = require('child_process')
- const fs = require('fs')
- // 公网访问域名(从环境变量读取,默认本地)
- const WEB_HOST = process.env.WEB_HOST || 'localhost:8080'
- const PUBLIC_HOST = WEB_HOST.startsWith('http') ? WEB_HOST : `https://${WEB_HOST}`
- // 小程序配置
- const MINI_CONFIGS = {
- enterprise: {
- name: '企业小程序',
- appid: 'wx1e791ed2e0229eb8',
- projectPath: path.resolve(__dirname, '../mini/dist/weapp/production'),
- privateKeyPath: path.resolve(__dirname, '../mini/certs/private.upload.key'),
- buildCmd: 'cd mini && pnpm build:weapp',
- distPath: 'dist/weapp',
- },
- talent: {
- name: '人才小程序',
- appid: 'wx3c47dbce1ea7d43c',
- projectPath: path.resolve(__dirname, '../mini-talent/dist/weapp/production'),
- privateKeyPath: path.resolve(__dirname, '../mini-talent/certs/private.upload.key'),
- buildCmd: 'cd mini-talent && pnpm build:weapp',
- distPath: 'dist/weapp',
- },
- }
- /**
- * 构建小程序
- */
- function buildMiniProject(config) {
- console.log(`\n🔨 正在构建 ${config.name}...`)
- try {
- execSync(config.buildCmd, { stdio: 'inherit' })
- console.log(`✅ ${config.name} 构建完成`)
- } catch (error) {
- console.error(`❌ ${config.name} 构建失败`)
- throw error
- }
- }
- /**
- * 发布小程序体验版到微信服务器
- */
- async function uploadExperienceProject(config, options) {
- const { version, desc, robot = 1 } = options
- console.log(`\n📤 正在发布体验版 ${config.name}...`)
- console.log(` 版本: ${version}`)
- console.log(` 描述: ${desc}`)
- const project = new ci.Project({
- appid: config.appid,
- type: 'miniProgram',
- projectPath: config.projectPath,
- privateKeyPath: config.privateKeyPath,
- ignores: ['node_modules/**/*'],
- })
- try {
- const result = await ci.upload({
- project,
- version,
- desc,
- setting: {
- useProjectConfig: true,
- es7: true,
- minify: true,
- minifyJS: true,
- minifyWXML: true,
- minifyWXSS: true,
- autoPrefixWXSS: true,
- },
- onProgressUpdate: (progress) => {
- process.stdout.write(`\r 上传进度: ${progress}%`)
- },
- robot,
- })
- console.log(`\n✅ ${config.name}体验版上传成功!`)
- console.log(` 时间: ${result.time}`)
- console.log(` 版本: ${result.version}`)
- console.log(` 请前往小程序后台查看: https://mp.weixin.qq.com/`)
- } catch (error) {
- console.error(`\n❌ ${config.name}体验版上传失败`)
- console.error(error.message)
- throw error
- }
- }
- /**
- * 预览小程序(生成二维码)
- */
- async function previewDevProject(config, options) {
- const { desc, robot = 1 } = options
- console.log(`\n👀 正在生成 ${config.name} 预览二维码...`)
- const project = new ci.Project({
- appid: config.appid,
- type: 'miniProgram',
- projectPath: config.projectPath,
- privateKeyPath: config.privateKeyPath,
- ignores: ['node_modules/**/*'],
- })
- // 二维码保存目录
- const qrcodeDir = path.resolve(__dirname, '../web/public/qrcode')
- const qrcodeFileName = `qrcode-${config.appid}.jpg`
- const qrcodePath = path.join(qrcodeDir, qrcodeFileName)
- // 确保 qrcode 目录存在
- if (!fs.existsSync(qrcodeDir)) {
- fs.mkdirSync(qrcodeDir, { recursive: true })
- }
- try {
- await ci.preview({
- project,
- desc,
- setting: { useProjectConfig: true },
- qrcodeFormat: 'image',
- qrcodeOutputDest: qrcodePath,
- onProgressUpdate: (progress) => {
- process.stdout.write(`\r 生成进度: ${progress}%`)
- },
- robot,
- })
- // 公网访问 URL
- const publicUrl = `${PUBLIC_HOST}/qrcode/${qrcodeFileName}`
- console.log(`\n✅ 开发版预览二维码已生成!`)
- console.log(`📱 本地路径: ${qrcodePath}`)
- console.log(`🌐 公网访问: ${publicUrl}`)
- console.log(`\n>>>QRCode_IMAGE_START<<<`)
- console.log(qrcodePath)
- console.log(`>>>QRCode_URL_START<<<`)
- console.log(publicUrl)
- console.log(`>>>QRCode_URL_END<<<`)
- } catch (error) {
- console.error(`\n❌ 开发版预览二维码生成失败`)
- console.error(error.message)
- throw error
- }
- }
- /**
- * 主函数
- */
- async function main() {
- const args = process.argv.slice(2)
- const noBuildIndex = args.indexOf('--no-build')
- const noBuild = noBuildIndex !== -1
- if (noBuild) {
- args.splice(noBuildIndex, 1)
- }
- const [miniType, action = 'experience'] = args
- // 解析参数
- const options = {
- version: process.env.VERSION || '1.0.0',
- desc: process.env.DESC || '自动化发布',
- robot: parseInt(process.env.ROBOT || '1'),
- }
- if (!miniType || !MINI_CONFIGS[miniType]) {
- console.error('❌ 请指定小程序类型: enterprise 或 talent')
- console.error('示例: node scripts/publish-weapp.js enterprise')
- process.exit(1)
- }
- const config = MINI_CONFIGS[miniType]
- try {
- // 构建项目(除非使用 --no-build)
- if (!noBuild) {
- buildMiniProject(config)
- } else {
- console.log(`\n⏭️ 跳过构建,使用现有构建输出`)
- }
- // 执行操作
- if (action === 'experience') {
- await uploadExperienceProject(config, options)
- } else if (action === 'dev') {
- await previewDevProject(config, {
- desc: options.desc,
- robot: options.robot,
- })
- } else {
- console.error(`❌ 操作无效: ${action}`)
- process.exit(1)
- }
- } catch (error) {
- process.exit(1)
- }
- }
- main()
|