|
@@ -0,0 +1,355 @@
|
|
|
|
|
+---
|
|
|
|
|
+name: weapp-publish
|
|
|
|
|
+description: 微信小程序发布工具。用于发布企业小程序和人才小程序的开发版和体验版,支持自动化构建、上传和预览流程。
|
|
|
|
|
+license: MIT
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+# 微信小程序发布 Skill
|
|
|
|
|
+
|
|
|
|
|
+本 Skill 专门用于本项目的企业小程序和人才小程序的自动化发布流程。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 支持的小程序
|
|
|
|
|
+
|
|
|
|
|
+| 小程序 | 目录 | AppID | 说明 |
|
|
|
|
|
+|--------|------|-------|------|
|
|
|
|
|
+| **企业小程序** | `mini/` | `wx1e791ed2e0229eb8` | 用人方小程序(企业管理端) |
|
|
|
|
|
+| **人才小程序** | `mini-talent/` | `wx3c47dbce1ea7d43c` | 人才小程序(求职者端) |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 发布前准备
|
|
|
|
|
+
|
|
|
|
|
+### 1. 安装 miniprogram-ci
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+pnpm add -D miniprogram-ci
|
|
|
|
|
+# 或全局安装
|
|
|
|
|
+pnpm add -g miniprogram-ci
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2. 获取上传密钥
|
|
|
|
|
+
|
|
|
|
|
+使用小程序管理员身份访问"微信公众平台 > 开发 > 开发设置",下载代码上传密钥。
|
|
|
|
|
+
|
|
|
|
|
+**企业小程序密钥文件**: `keys/private.wx1e791ed2e0229eb8.key`
|
|
|
|
|
+**人才小程序密钥文件**: `keys/private.wx3c47dbce1ea7d43c.key`
|
|
|
|
|
+
|
|
|
|
|
+### 3. 配置 IP 白名单
|
|
|
|
|
+
|
|
|
|
|
+在微信公众平台配置服务器的 IP 白名单。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 发布流程
|
|
|
|
|
+
|
|
|
|
|
+### 完整发布步骤
|
|
|
|
|
+
|
|
|
|
|
+1. **构建项目**: 运行 Taro 构建命令生成小程序代码
|
|
|
|
|
+2. **上传代码**: 使用 miniprogram-ci 上传到微信服务器
|
|
|
|
|
+3. **设置体验版**(可选): 在小程序后台将上传的版本设置为体验版
|
|
|
|
|
+
|
|
|
|
|
+### 发布命令
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 企业小程序 - 开发版上传
|
|
|
|
|
+pnpm run publish:enterprise:dev
|
|
|
|
|
+
|
|
|
|
|
+# 企业小程序 - 生产版上传
|
|
|
|
|
+pnpm run publish:enterprise:prod
|
|
|
|
|
+
|
|
|
|
|
+# 人才小程序 - 开发版上传
|
|
|
|
|
+pnpm run publish:talent:dev
|
|
|
|
|
+
|
|
|
|
|
+# 人才小程序 - 生产版上传
|
|
|
|
|
+pnpm run publish:talent:prod
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 脚本实现
|
|
|
|
|
+
|
|
|
|
|
+### 创建发布脚本
|
|
|
|
|
+
|
|
|
|
|
+在项目根目录创建 `scripts/publish-weapp.js`:
|
|
|
|
|
+
|
|
|
|
|
+```javascript
|
|
|
|
|
+const ci = require('miniprogram-ci')
|
|
|
|
|
+const path = require('path')
|
|
|
|
|
+const { execSync } = require('child_process')
|
|
|
|
|
+
|
|
|
|
|
+// 小程序配置
|
|
|
|
|
+const MINI_CONFIGS = {
|
|
|
|
|
+ enterprise: {
|
|
|
|
|
+ name: '企业小程序',
|
|
|
|
|
+ appid: 'wx1e791ed2e0229eb8',
|
|
|
|
|
+ projectPath: path.resolve(__dirname, '../mini'),
|
|
|
|
|
+ privateKeyPath: path.resolve(__dirname, '../keys/private.wx1e791ed2e0229eb8.key'),
|
|
|
|
|
+ buildCmd: 'cd mini && pnpm build:weapp',
|
|
|
|
|
+ distPath: 'dist/weapp',
|
|
|
|
|
+ },
|
|
|
|
|
+ talent: {
|
|
|
|
|
+ name: '人才小程序',
|
|
|
|
|
+ appid: 'wx3c47dbce1ea7d43c',
|
|
|
|
|
+ projectPath: path.resolve(__dirname, '../mini-talent'),
|
|
|
|
|
+ privateKeyPath: path.resolve(__dirname, '../keys/private.wx3c47dbce1ea7d43c.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 uploadMiniProject(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 previewMiniProject(config, options) {
|
|
|
|
|
+ const { desc, qrcodePath, 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/**/*'],
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const result = await ci.preview({
|
|
|
|
|
+ project,
|
|
|
|
|
+ desc,
|
|
|
|
|
+ setting: { useProjectConfig: true },
|
|
|
|
|
+ qrcodeFormat: 'image',
|
|
|
|
|
+ qrcodeOutputDest: qrcodePath,
|
|
|
|
|
+ onProgressUpdate: (progress) => {
|
|
|
|
|
+ process.stdout.write(`\r 生成进度: ${progress}%`)
|
|
|
|
|
+ },
|
|
|
|
|
+ robot,
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`\n✅ 预览二维码已生成: ${qrcodePath}`)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error(`\n❌ 预览二维码生成失败`)
|
|
|
|
|
+ console.error(error.message)
|
|
|
|
|
+ throw error
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 主函数
|
|
|
|
|
+ */
|
|
|
|
|
+async function main() {
|
|
|
|
|
+ const args = process.argv.slice(2)
|
|
|
|
|
+ const [miniType, action = 'upload'] = 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('示例: pnpm run publish:enterprise')
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const config = MINI_CONFIGS[miniType]
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 构建项目
|
|
|
|
|
+ buildMiniProject(config)
|
|
|
|
|
+
|
|
|
|
|
+ // 执行操作
|
|
|
|
|
+ if (action === 'upload') {
|
|
|
|
|
+ await uploadMiniProject(config, options)
|
|
|
|
|
+ } else if (action === 'preview') {
|
|
|
|
|
+ await previewMiniProject(config, {
|
|
|
|
|
+ desc: options.desc,
|
|
|
|
|
+ qrcodePath: path.resolve(__dirname, `../qrcode-${miniType}.jpg`),
|
|
|
|
|
+ robot: options.robot,
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.error(`❌ 未知操作: ${action}`)
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+main()
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## package.json 配置
|
|
|
|
|
+
|
|
|
|
|
+在根目录 `package.json` 中添加以下脚本:
|
|
|
|
|
+
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "scripts": {
|
|
|
|
|
+ "publish:enterprise": "node scripts/publish-weapp.js enterprise upload",
|
|
|
|
|
+ "publish:enterprise:preview": "node scripts/publish-weapp.js enterprise preview",
|
|
|
|
|
+ "publish:talent": "node scripts/publish-weapp.js talent upload",
|
|
|
|
|
+ "publish:talent:preview": "node scripts/publish-weapp.js talent preview"
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 环境变量配置
|
|
|
|
|
+
|
|
|
|
|
+创建 `.env.local` 文件:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 发布版本号
|
|
|
|
|
+VERSION=1.0.0
|
|
|
|
|
+
|
|
|
|
|
+# 发布描述
|
|
|
|
|
+DESC=修复了一些问题并优化了用户体验
|
|
|
|
|
+
|
|
|
|
|
+# CI 机器人编号 (1-30)
|
|
|
|
|
+ROBOT=1
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 使用示例
|
|
|
|
|
+
|
|
|
|
|
+### 发布企业小程序
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 使用默认版本号和描述
|
|
|
|
|
+pnpm run publish:enterprise
|
|
|
|
|
+
|
|
|
|
|
+# 自定义版本号和描述
|
|
|
|
|
+VERSION=1.2.0 DESC="新增订单管理功能" pnpm run publish:enterprise
|
|
|
|
|
+
|
|
|
|
|
+# 生成预览二维码
|
|
|
|
|
+pnpm run publish:enterprise:preview
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 发布人才小程序
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 使用默认版本号和描述
|
|
|
|
|
+pnpm run publish:talent
|
|
|
|
|
+
|
|
|
|
|
+# 自定义版本号和描述
|
|
|
|
|
+VERSION=2.0.0 DESC="全新改版,优化求职流程" pnpm run publish:talent
|
|
|
|
|
+
|
|
|
|
|
+# 生成预览二维码
|
|
|
|
|
+pnpm run publish:talent:preview
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 快捷命令建议
|
|
|
|
|
+
|
|
|
|
|
+用户可以直接询问 Claude 执行以下操作:
|
|
|
|
|
+
|
|
|
|
|
+| 用户指令 | Claude 行为 |
|
|
|
|
|
+|----------|-------------|
|
|
|
|
|
+| "发布企业小程序" | 运行 `pnpm run publish:enterprise` |
|
|
|
|
|
+| "发布人才小程序" | 运行 `pnpm run publish:talent` |
|
|
|
|
|
+| "生成企业小程序预览二维码" | 运行 `pnpm run publish:enterprise:preview` |
|
|
|
|
|
+| "发布两个小程序" | 依次运行企业小程序和人才小程序的发布命令 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 注意事项
|
|
|
|
|
+
|
|
|
|
|
+1. **密钥安全**: 上传密钥拥有预览、上传权限,请勿提交到代码仓库
|
|
|
|
|
+2. **构建依赖**: 发布前确保项目依赖已安装 (`pnpm install`)
|
|
|
|
|
+3. **版本管理**: 建议使用语义化版本号 (Semantic Versioning)
|
|
|
|
|
+4. **IP 白名单**: 确保服务器 IP 已在微信公众平台配置白名单
|
|
|
|
|
+5. **机器人编号**: 多个 CI 并发时使用不同的 robot 编号 (1-30)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 常见问题
|
|
|
|
|
+
|
|
|
|
|
+### Q: 上传失败提示 IP 不在白名单
|
|
|
|
|
+**A**: 请在微信公众平台"开发 > 开发设置"中添加服务器 IP 到白名单。
|
|
|
|
|
+
|
|
|
|
|
+### Q: 构建成功但上传失败
|
|
|
|
|
+**A**: 检查密钥文件路径是否正确,密钥是否匹配对应的 AppID。
|
|
|
|
|
+
|
|
|
|
|
+### Q: 如何设置体验版
|
|
|
|
|
+**A**: 上传成功后,登录小程序后台"版本管理",将指定版本设置为体验版。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 相关资源
|
|
|
|
|
+
|
|
|
|
|
+- [miniprogram-ci 官方文档](https://www.npmjs.com/package/miniprogram-ci)
|
|
|
|
|
+- [微信公众平台](https://mp.weixin.qq.com/)
|
|
|
|
|
+- [miniprogram-ci Skill](.claude/skills/miniprogram-ci/SKILL.md)
|