From 6eb748a902ba7df1435036ca0eabe3de8340e6f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=98=E9=A3=8E?= Date: Wed, 4 Feb 2026 16:19:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E4=BA=8C=E7=BB=B4=E7=A0=81=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E4=B8=BA=E8=B0=83=E7=94=A8=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=94=9F=E6=88=90=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E7=A0=81=E5=B9=B6=E4=BF=9D=E5=AD=98=E4=B8=BA=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=9B=E5=90=8C=E6=97=B6=E5=9C=A8=20devlop?= =?UTF-8?q?=20=E8=84=9A=E6=9C=AC=E4=B8=AD=E7=BB=9F=E4=B8=80=20SSH=20?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=8F=AF=E7=BB=B4=E6=8A=A4=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- miniprogram/pages/referral/referral.js | 45 +++++++++++++++++++++++--- scripts/devlop.py | 24 +++++++------- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/miniprogram/pages/referral/referral.js b/miniprogram/pages/referral/referral.js index bb3afc8a..b46beb9d 100644 --- a/miniprogram/pages/referral/referral.js +++ b/miniprogram/pages/referral/referral.js @@ -266,15 +266,50 @@ Page({ this.setData({ showPosterModal: true, isGeneratingPoster: true }) try { - // Next.js 的实现:只生成一个二维码图片(不做画布海报) const { referralCode, userInfo } = this.data - const referralLink = `https://soul.quwanzhi.com/?ref=${referralCode}` - const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=320x320&data=${encodeURIComponent(referralLink)}` const nickname = userInfo?.nickname || '用户' + const scene = `ref=${referralCode}` + + console.log('[Poster] 请求小程序码, scene:', scene) + + // 调用后端接口生成「小程序码」(官方 getwxacodeunlimit),不再使用 H5 二维码 + const res = await app.request('/api/miniprogram/qrcode', { + method: 'POST', + data: { + scene, // ref=XXXX + page: 'pages/index/index', + width: 280, + }, + }) + + if (!res || !res.success || !res.image) { + console.error('[Poster] 生成小程序码失败:', res) + throw new Error(res?.error || '生成小程序码失败') + } + + // 后端返回的是 data:image/png;base64,... 需要先写入本地临时文件,再作为 的 src + const base64Data = String(res.image).replace(/^data:image\/\w+;base64,/, '') + const fs = wx.getFileSystemManager() + const filePath = `${wx.env.USER_DATA_PATH}/poster_qrcode_${Date.now()}.png` + + await new Promise((resolve, reject) => { + fs.writeFile({ + filePath, + data: base64Data, + encoding: 'base64', + success: () => resolve(true), + fail: (err) => { + console.error('[Poster] 小程序码写入本地失败:', err) + reject(err) + }, + }) + }) + + console.log('[Poster] 小程序码已保存到本地:', filePath) this.setData({ - posterQrSrc: qrUrl, - posterReferralLink: referralLink, + posterQrSrc: filePath, + posterReferralLink: '', // 小程序版本不再使用 H5 链接 posterNickname: nickname, posterNicknameInitial: (nickname || '用').charAt(0), isGeneratingPoster: false diff --git a/scripts/devlop.py b/scripts/devlop.py index 56a46346..2c9d5c2a 100644 --- a/scripts/devlop.py +++ b/scripts/devlop.py @@ -39,6 +39,8 @@ DEPLOY_PM2_APP = "soul" DEFAULT_DEPLOY_PORT = 30006 DEPLOY_PROJECT_PATH = "/www/wwwroot/soul" DEPLOY_SITE_URL = "https://soul.quwanzhi.com" +# SSH 端口(支持环境变量 DEPLOY_SSH_PORT,未设置时默认为 22022) +DEFAULT_SSH_PORT = int(os.environ.get("DEPLOY_SSH_PORT", "22022")) def get_cfg(): """获取基础部署配置(deploy 模式与 devlop 共用 SSH/宝塔)""" @@ -324,9 +326,9 @@ def check_node_environments(cfg): client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: if cfg.get("ssh_key"): - client.connect(cfg["host"], username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) else: - client.connect(cfg["host"], username=cfg["user"], password=cfg["password"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], password=cfg["password"], timeout=15) stdin, stdout, stderr = client.exec_command("which node && node -v", timeout=10) print(" 默认 Node: %s" % (stdout.read().decode("utf-8", errors="replace").strip() or "未找到")) node_path = cfg.get("node_path", "/www/server/nodejs/v22.14.0/bin") @@ -350,9 +352,9 @@ def upload_and_extract(cfg, tarball_path): client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: if cfg.get("ssh_key") and os.path.isfile(cfg["ssh_key"]): - client.connect(cfg["host"], username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) else: - client.connect(cfg["host"], username=cfg["user"], password=cfg["password"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], password=cfg["password"], timeout=15) sftp = client.open_sftp() remote_tar = "/tmp/soulTest_deploy.tar.gz" remote_script = "/tmp/soulTest_deploy_extract.sh" @@ -515,12 +517,12 @@ def upload_zip_and_extract_to_dist2(cfg, zip_path): client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: - print(" 正在连接 %s@%s ..." % (cfg["user"], cfg["host"])) + print(" 正在连接 %s@%s:%s ..." % (cfg["user"], cfg["host"], DEFAULT_SSH_PORT)) sys.stdout.flush() if cfg.get("ssh_key") and os.path.isfile(cfg["ssh_key"]): - client.connect(cfg["host"], username=cfg["user"], key_filename=cfg["ssh_key"], timeout=30, banner_timeout=30) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], key_filename=cfg["ssh_key"], timeout=30, banner_timeout=30) else: - client.connect(cfg["host"], username=cfg["user"], password=cfg["password"], timeout=30, banner_timeout=30) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], password=cfg["password"], timeout=30, banner_timeout=30) print(" [OK] SSH 已连接,正在上传 zip(%.1f MB)..." % zip_size_mb) sys.stdout.flush() remote_zip = cfg["base_path"].rstrip("/") + "/soulTest_devlop.zip" @@ -575,9 +577,9 @@ def run_pnpm_install_in_dist2(cfg): client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: if cfg.get("ssh_key") and os.path.isfile(cfg["ssh_key"]): - client.connect(cfg["host"], username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) else: - client.connect(cfg["host"], username=cfg["user"], password=cfg["password"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], password=cfg["password"], timeout=15) stdin, stdout, stderr = client.exec_command("bash -lc 'which pnpm'", timeout=10) pnpm_path = stdout.read().decode("utf-8", errors="replace").strip() if not pnpm_path: @@ -606,9 +608,9 @@ def remote_swap_dist_and_restart(cfg): client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: if cfg.get("ssh_key") and os.path.isfile(cfg["ssh_key"]): - client.connect(cfg["host"], username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], key_filename=cfg["ssh_key"], timeout=15) else: - client.connect(cfg["host"], username=cfg["user"], password=cfg["password"], timeout=15) + client.connect(cfg["host"], port=DEFAULT_SSH_PORT, username=cfg["user"], password=cfg["password"], timeout=15) cmd = "cd %s && mv dist dist1 2>/dev/null; mv dist2 dist && rm -rf dist1 && echo OK" % cfg["base_path"] stdin, stdout, stderr = client.exec_command(cmd, timeout=60) out = stdout.read().decode("utf-8", errors="replace").strip()