From e6288a1f09cbe61341a99118165708d5194c79f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E5=B2=A9?= Date: Mon, 10 Nov 2025 10:00:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=8F=91=E4=B8=AD=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 +- devops/iso/新的/AuthKey_ACRB9XFL9G.p8 | 6 + devops/iso/新的/build_ios.py | 182 ++++++++ .../DistributionSummary.plist | 59 +++ .../新的/build_ios_config/ExportOptions.plist | 31 ++ devops/iso/新的/git_update_remote.sh | 88 ++++ devops/iso/新的/ipa_server.py | 101 +++++ devops/iso/新的/push_version.py | 402 ++++++++++++++++++ devops/iso/新的/ready_build_ios.sh | 95 +++++ devops/iso/新的/show.py | 6 + devops/iso/新的/sync_remote_branch.py | 121 ++++++ devops/iso/新的/upload_to_appstore.py | 144 +++++++ devops/iso/新的/validate_and_upload.sh | 92 ++++ devops/iso/老的/AuthKey_ACRB9XFL9G.p8 | 6 + devops/iso/老的/git_update_remote.sh | 88 ++++ devops/iso/老的/push_version.py | 382 +++++++++++++++++ devops/iso/老的/ready_build_ios.sh | 95 +++++ devops/iso/老的/validate_and_upload.sh | 92 ++++ src/api/request.js | 2 +- src/components/points-and-badge/badge.vue | 303 ++++++++++++- src/components/points-and-badge/check-in.vue | 40 +- src/components/points-and-badge/points.vue | 169 +++++++- src/pages/me/index.vue | 35 +- src/static/images/pointsAndRank/like.png | Bin 0 -> 85216 bytes 24 files changed, 2497 insertions(+), 44 deletions(-) create mode 100644 devops/iso/新的/AuthKey_ACRB9XFL9G.p8 create mode 100644 devops/iso/新的/build_ios.py create mode 100644 devops/iso/新的/build_ios_config/DistributionSummary.plist create mode 100644 devops/iso/新的/build_ios_config/ExportOptions.plist create mode 100644 devops/iso/新的/git_update_remote.sh create mode 100644 devops/iso/新的/ipa_server.py create mode 100644 devops/iso/新的/push_version.py create mode 100644 devops/iso/新的/ready_build_ios.sh create mode 100644 devops/iso/新的/show.py create mode 100644 devops/iso/新的/sync_remote_branch.py create mode 100644 devops/iso/新的/upload_to_appstore.py create mode 100644 devops/iso/新的/validate_and_upload.sh create mode 100644 devops/iso/老的/AuthKey_ACRB9XFL9G.p8 create mode 100644 devops/iso/老的/git_update_remote.sh create mode 100644 devops/iso/老的/push_version.py create mode 100644 devops/iso/老的/ready_build_ios.sh create mode 100644 devops/iso/老的/validate_and_upload.sh create mode 100644 src/static/images/pointsAndRank/like.png diff --git a/.env.development b/.env.development index fb24b9b4..bdea487e 100644 --- a/.env.development +++ b/.env.development @@ -4,7 +4,7 @@ ENV = 'development' # VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001' -VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002' +VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001' # VITE_APP_BASE_API_Url = 'http://192.168.247.200' # VITE_APP_BASE_API_Url = 'http://aitscdn.jlbank.com.cn:7001' # VITE_APP_BASE_API_Url = 'http://192.168.108.129' diff --git a/devops/iso/新的/AuthKey_ACRB9XFL9G.p8 b/devops/iso/新的/AuthKey_ACRB9XFL9G.p8 new file mode 100644 index 00000000..c209d906 --- /dev/null +++ b/devops/iso/新的/AuthKey_ACRB9XFL9G.p8 @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgZfELkUrcpqqAVlQg +UfKNlPbySAnafYL+vEndTe9/xoqgCgYIKoZIzj0DAQehRANCAATBz1/RZd+1AEgU +VfnoB1PNUMynS8FQ/zJdTcZ25qEuu6WVkWb82Ltmb1lIRSZpRWEbpQzL+7X6zQ95 +yjRmUksW +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/devops/iso/新的/build_ios.py b/devops/iso/新的/build_ios.py new file mode 100644 index 00000000..cc7f5ee5 --- /dev/null +++ b/devops/iso/新的/build_ios.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +import os +import subprocess +import sys +import shutil +from datetime import datetime + +# 颜色定义 +RED = '\033[0;31m' +GREEN = '\033[0;32m' +YELLOW = '\033[1;33m' +BLUE = '\033[0;34m' +NC = '\033[0m' # 无颜色 + +def run_command(command, check=True, capture_output=False): + """执行系统命令并返回结果""" + try: + if capture_output: + result = subprocess.run( + command, + shell=True, + check=check, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + return result + else: + subprocess.run(command, shell=True, check=check) + return None + except subprocess.CalledProcessError as e: + print(f"{RED}❌ 命令执行失败: {e.stderr}{NC}") + sys.exit(1) + +def main(): + # 检查参数 + if len(sys.argv) < 4: + print(f"{RED}错误:参数不足!{NC}") + print(f"使用方法:{YELLOW}{sys.argv[0]} {NC}") + print(f"示例:{YELLOW}{sys.argv[0]} sit 1.0.0 1{NC}") + sys.exit(1) + + # 解析参数(第一个参数为target_branch,原参数顺延) + target_branch = sys.argv[1] + marketing_version = sys.argv[2] + current_project_version = sys.argv[3] + + # ============================================== + # 配置参数 - 请根据实际情况修改以下参数 + # ============================================== + # 钥匙串配置 + keychain_password = "1234567" # 钥匙串密码 + keychain_path = f"{os.path.expanduser('~')}/Library/Keychains/login.keychain-db" # 钥匙串路径 + + # 项目路径配置(可根据需要结合target_branch调整路径) + script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) + parent_dir = os.path.dirname(script_dir) + work_dir = os.path.join(parent_dir, "build", target_branch, 'Ios','HBuilder-Hello') + project_dir = os.path.abspath(work_dir) + project_name = "HBuilder-Hello.xcodeproj" # Xcode项目文件名 + scheme_name = "HBuilder" # 构建方案名称 + configuration = "Release" # 构建配置 + + + # 构建输出配置 + build_dir = f"{os.path.expanduser('~')}/Desktop/lx_uniapp/build" # 构建输出目录 + archive_name = "HBuilder.xcarchive" # 归档文件名 + ipa_dir_name = f"{target_branch}_ipa_production" # IPA输出目录名(带分支名) + derived_data_dir = f"{os.path.expanduser('~')}/Library/Developer/Xcode/DerivedData/*" # 衍生数据目录 + + # 签名配置 + code_sign_identity = "Apple Distribution: Bank of Jilin Co., Ltd. (2EP6SRRN43)" # 签名标识 + provisioning_profile = "e3487fe1-19dc-4fc7-90df-11caf27da0c6" # 配置文件UUID + development_team = "2EP6SRRN43" # 开发团队ID + code_signing_required = "YES" # 是否需要签名 + + # 导出配置 + export_options_plist = os.path.join(script_dir, "build_ios_config", "ExportOptions.plist") + # 转换为绝对路径(跨平台兼容) + export_options_plist = os.path.abspath(export_options_plist) + # ============================================== + + # 显示参数信息 + print(f"\n{BLUE}===== 构建参数信息 ====={NC}") + print(f"▶ 目标分支: {YELLOW}{target_branch}{NC}") + print(f"▶ 市场版本号: {YELLOW}{marketing_version}{NC}") + print(f"▶ 内部版本号: {YELLOW}{current_project_version}{NC}") + print(f"▶ 项目目录: {YELLOW}{project_dir}{NC}\n") + + # 0. 解锁钥匙串并授予权限 + print(f"{BLUE}🔑 解锁钥匙串...{NC}") + run_command(f"security unlock-keychain -p '{keychain_password}' '{keychain_path}'") + + # 1. 进入项目目录 + print(f"{BLUE}📂 进入项目目录: {project_dir}{NC}") + try: + os.chdir(project_dir) + except OSError as e: + print(f"{RED}❌ 无法进入项目目录: {e}{NC}") + sys.exit(1) + + # 2. 清理旧构建 + print(f"{BLUE}🧹 清理旧构建...{NC}") + run_command( + f"xcodebuild -project '{project_name}' " + f"-scheme '{scheme_name}' " + f"-configuration '{configuration}' clean" + ) + + # 3. 删除上次构建内容 + print(f"{BLUE}🗑️ 删除上次构建内容...{NC}") + # 拼接路径 + + ipa_dir_path = f"{build_dir}/{ipa_dir_name}" + archive_path = f"{build_dir}/{ipa_dir_name}/{archive_name}" + # 删除文件/目录 + for path in [ipa_dir_path, derived_data_dir]: + if os.path.exists(path) or '*' in path: # 处理通配符 + run_command(f"rm -rf '{path}'", check=False) + + # 4. 归档项目 + print(f"{BLUE}📦 开始归档项目...{NC}") + run_command( + f"xcodebuild -project '{project_name}' " + f"-scheme '{scheme_name}' " + f"-configuration '{configuration}' " + f"-archivePath '{archive_path}' " + f"MARKETING_VERSION='{marketing_version}' " + f"CURRENT_PROJECT_VERSION='{current_project_version}' " + f"-destination 'generic/platform=iOS' " + f"CODE_SIGN_IDENTITY='{code_sign_identity}' " + f"PROVISIONING_PROFILE='{provisioning_profile}' " + f"DEVELOPMENT_TEAM='{development_team}' " + f"CODE_SIGNING_REQUIRED='{code_signing_required}' " + f"OTHER_CFLAGS='' " + f"OTHER_CPLUSPLUS_FLAGS='' " + f"OTHER_SWIFT_FLAGS='' " + f"archive" + ) + + # 5. 导出IPA文件 + print(f"{BLUE}📤 导出IPA文件...{NC}") + run_command( + f"xcodebuild -exportArchive " + f"-archivePath '{archive_path}' " + f"-exportPath '{build_dir}/{ipa_dir_name}' " + f"-exportOptionsPlist '{export_options_plist}'" + ) + + print(f"\n{GREEN}🎉 构建完成!IPA文件已导出至: {build_dir}/{ipa_dir_name}{NC}") + # 6. 复制并重命名IPA文件到共享目录 + print(f"{BLUE}📋 复制IPA文件到共享目录...{NC}") + + # 定义共享目录路径 + share_dir = "/Users/Shared/lx_uniapp_build_for_share" + + # 确保共享目录存在(不存在则创建) + os.makedirs(share_dir, exist_ok=True) + + # 获取当前时间(格式:YYYYMMDDHHMM) + current_time = datetime.now().strftime("%Y%m%d%H%M") + + # 构建新文件名(jax-<分支名>-<版本号>-<当前时间>.ipa) + new_ipa_name = f"jax-{target_branch}-{current_project_version}-{current_time}.ipa" + + # 源IPA文件路径(基于之前的导出路径) + source_ipa = os.path.join(build_dir, ipa_dir_name, "HBuilder.ipa") + + # 目标IPA文件路径 + target_ipa = os.path.join(share_dir, new_ipa_name) + + # 复制并覆盖文件 + try: + shutil.copy2(source_ipa, target_ipa) # copy2 会保留文件元数据 + print(f"{GREEN}✅ IPA文件已复制至共享目录:{target_ipa}{NC}") + except FileNotFoundError: + print(f"{RED}❌ 源IPA文件不存在:{source_ipa}{NC}") + except Exception as e: + print(f"{RED}❌ 复制IPA文件失败:{str(e)}{NC}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/devops/iso/新的/build_ios_config/DistributionSummary.plist b/devops/iso/新的/build_ios_config/DistributionSummary.plist new file mode 100644 index 00000000..5587ce10 --- /dev/null +++ b/devops/iso/新的/build_ios_config/DistributionSummary.plist @@ -0,0 +1,59 @@ + + + + + HBuilder.ipa + + + architectures + + arm64 + + buildNumber + 114 + certificate + + SHA1 + D24C7C1BFC6616660E24A8893EF27E23D1C6109F + dateExpires + 2026/7/18 + type + Apple Distribution + + entitlements + + application-identifier + 2EP6SRRN43.cn.com.jlbank.aits + beta-reports-active + + com.apple.developer.team-identifier + 2EP6SRRN43 + get-task-allow + + + name + HBuilder.app + profile + + UUID + e3487fe1-19dc-4fc7-90df-11caf27da0c6 + dateExpires + 2026/7/18 + name + jiaixue-pro + + symbols + + team + + id + 2EP6SRRN43 + name + + + versionNumber + 0.2.1 + + + + diff --git a/devops/iso/新的/build_ios_config/ExportOptions.plist b/devops/iso/新的/build_ios_config/ExportOptions.plist new file mode 100644 index 00000000..5e2a3068 --- /dev/null +++ b/devops/iso/新的/build_ios_config/ExportOptions.plist @@ -0,0 +1,31 @@ + + + + + destination + export + generateAppStoreInformation + + manageAppVersionAndBuildNumber + + method + app-store-connect + provisioningProfiles + + cn.com.jlbank.aits + e3487fe1-19dc-4fc7-90df-11caf27da0c6 + + signingCertificate + Apple Distribution: Bank of Jilin Co., Ltd. (2EP6SRRN43) + signingStyle + manual + stripSwiftSymbols + + teamID + 2EP6SRRN43 + testFlightInternalTestingOnly + + uploadSymbols + + + diff --git a/devops/iso/新的/git_update_remote.sh b/devops/iso/新的/git_update_remote.sh new file mode 100644 index 00000000..8c7947db --- /dev/null +++ b/devops/iso/新的/git_update_remote.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# 脚本名称:sync_remote_branch.sh +# 功能描述:修复origin/sit引用问题,强制同步远程分支到本地develop +# 使用方法:./sync_remote_branch.sh <远程分支名> + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# 检查参数 +if [ $# -eq 0 ]; then + echo -e "${RED}错误:未传入分支名称参数!${NC}" + echo -e "使用方法:${YELLOW}$0 <远程分支名>${NC}" + exit 1 +fi +echo -e "▶ 先设置内网网络\n" +sudo route add -host 25.13.9.101 25.64.32.254 +# 配置参数 +TARGET_BRANCH="$1" +WORK_DIR="Desktop/lx_uniapp/build/git_work_code" +REMOTE_NAME="origin" +LOCAL_BRANCH="develop" + +echo -e "\n${YELLOW}===== 开始执行分支同步脚本 =====${NC}" +echo -e "▶ 远程目标分支:${YELLOW}${TARGET_BRANCH}${NC}" +echo -e "▶ 本地工作目录:${YELLOW}${WORK_DIR}${NC}\n" + +# 1. 进入工作目录 +echo -e "${YELLOW}1. 检查并进入工作目录...${NC}" +if [ ! -d "$WORK_DIR" ]; then + echo -e "${RED}错误:工作目录不存在!${NC}" + exit 1 +fi +cd "$WORK_DIR" || { + echo -e "${RED}错误:无法进入工作目录!${NC}" + exit 1 +} +echo -e "✅ 成功进入工作目录:$(pwd)\n" + +# 2. 检查Git仓库 +echo -e "${YELLOW}2. 检查Git仓库...${NC}" +if [ ! -d ".git" ]; then + echo -e "${RED}错误:当前目录不是Git仓库!${NC}" + exit 1 +fi +echo -e "✅ 确认是Git仓库\n" + +# 3. 关键修复:获取远程分支完整信息(不限制深度) +echo -e "${YELLOW}3. 完整获取远程所有分支完整信息...${NC}" +# 先移除可能存在的浅层克隆限制 +git config --unset core.depth +# 完整拉取所有分支信息 +if ! git fetch "$REMOTE_NAME" "+refs/heads/*:refs/remotes/$REMOTE_NAME/*"; then + echo -e "${RED}错误:拉取远程分支信息失败!${NC}" + exit 1 +fi +echo -e "✅ 远程分支信息拉取完成\n" + +# 4. 再次检查远程分支是否存在 +echo -e "${YELLOW}4. 验证远程 ${TARGET_BRANCH} 分支...${NC}" +if ! git show-ref --verify --quiet "refs/remotes/$REMOTE_NAME/$TARGET_BRANCH"; then + echo -e "${RED}错误:远程确实不存在 ${TARGET_BRANCH} 分支!${NC}" + echo -e "远程所有分支列表:" + git branch -r + exit 1 +fi +echo -e "✅ 确认远程存在 ${YELLOW}${TARGET_BRANCH}${NC} 分支\n" + +# 5. 同步到本地develop分支 +echo -e "${YELLOW}5. 同步远程 ${TARGET_BRANCH} 到本地 ${LOCAL_BRANCH}...${NC}" +echo -e "${YELLOW}⚠️ 警告:将覆盖本地develop分支所有内容!${NC}" + +# 确保本地有develop分支 +git checkout -B "$LOCAL_BRANCH" >/dev/null 2>&1 + +# 关键命令:使用完整引用路径 +if ! git reset --hard "refs/remotes/$REMOTE_NAME/$TARGET_BRANCH"; then + echo -e "${RED}错误:同步远程分支到本地失败!${NC}" + exit 1 +fi + +# 6. 完成提示 +echo -e "\n${GREEN}===== 操作完成 =====${NC}" +echo -e "✅ 本地 ${YELLOW}${LOCAL_BRANCH}${NC} 已同步为远程 ${YELLOW}${TARGET_BRANCH}${NC} 最新状态" +echo -e "当前版本:" +git log -1 --pretty=format:"%h - %an, %ar : %s" diff --git a/devops/iso/新的/ipa_server.py b/devops/iso/新的/ipa_server.py new file mode 100644 index 00000000..8c59bd61 --- /dev/null +++ b/devops/iso/新的/ipa_server.py @@ -0,0 +1,101 @@ +#!/opt/miniconda3/bin/python3 +import os +import sys +import socket +import http.server +import socketserver +import subprocess +from urllib.parse import urlparse + +# 配置基础路径和端口(推荐使用 1024-65535 之间的端口,避免系统预留端口) +BUILD_DIR = os.path.join(os.path.expanduser('~'), 'Desktop', 'lx_uniapp', 'build') +DEFAULT_PORT = 8000 # 若仍失败,可改为 8080、9000 等 + + +def check_port_available(port): + """检查端口是否真的可用(比 lsof 更可靠)""" + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + try: + s.bind(("", port)) # 尝试绑定端口,成功则可用 + return True + except OSError: + return False + + +def free_port(port): + """释放占用端口的进程""" + try: + result = subprocess.check_output( + f"lsof -i :{port} | grep LISTEN | awk '{{print $2}}'", + shell=True, + text=True, + stderr=subprocess.STDOUT # 忽略错误输出 + ) + pids = [pid.strip() for pid in result.split('\n') if pid.strip()] + if pids: + print(f"释放端口 {port} 占用的进程:{pids}") + for pid in pids: + subprocess.run(f"kill -9 {pid}", shell=True, check=True) + except subprocess.CalledProcessError: + pass # 无进程占用时正常 + except Exception as e: + print(f"释放端口警告:{e}(可忽略)") + + +class IPARequestHandler(http.server.SimpleHTTPRequestHandler): + # 省略与之前相同的 do_GET 实现(保持不变) + def do_GET(self): + parsed_path = urlparse(self.path) + target_branch = parsed_path.path.strip('/') + + if not target_branch: + self.send_response(400) + self.end_headers() + self.wfile.write("请指定分支名,例如: http://服务器IP:端口/sit".encode('utf-8')) + return + + ipa_dir_name = f"{target_branch}_ipa_production" + ipa_path = os.path.join(BUILD_DIR, ipa_dir_name, "HBuilder.ipa") + + if not os.path.exists(ipa_path): + self.send_response(404) + self.end_headers() + self.wfile.write(f"文件不存在: {ipa_path}".encode('utf-8')) + return + + self.send_response(200) + self.send_header('Content-Type', 'application/octet-stream') + self.send_header('Content-Disposition', f'attachment; filename="HBuilder_{target_branch}.ipa"') + self.end_headers() + + with open(ipa_path, 'rb') as f: + self.wfile.write(f.read()) + + +if __name__ == '__main__': + # 1. 先尝试释放端口 + free_port(DEFAULT_PORT) + + # 2. 检查端口是否真的可用 + if not check_port_available(DEFAULT_PORT): + print(f"端口 {DEFAULT_PORT} 仍被占用,尝试自动切换端口...") + # 自动切换到 8080 端口(若 8000 不可用) + DEFAULT_PORT = 8080 + free_port(DEFAULT_PORT) + if not check_port_available(DEFAULT_PORT): + print(f"端口 {DEFAULT_PORT} 也被占用,请手动指定其他端口(如 9000)") + sys.exit(1) + + # 3. 启动服务(增加错误捕获) + try: + # 禁用地址重用限制(解决 TIME_WAIT 状态导致的启动失败) + socketserver.TCPServer.allow_reuse_address = True + with socketserver.TCPServer(("", DEFAULT_PORT), IPARequestHandler) as httpd: + print(f"\nIPA 文件服务已启动,端口: {DEFAULT_PORT}") + print(f"访问格式: http://服务器IP:{DEFAULT_PORT}/目标分支名") + print(f"示例: http://25.64.32.152:{DEFAULT_PORT}/sit") + httpd.serve_forever() + except Exception as e: + print(f"服务启动失败:{str(e)}") + print("可能原因:权限不足(尝试非 1-1024 端口)或网络配置限制") + sys.exit(1) \ No newline at end of file diff --git a/devops/iso/新的/push_version.py b/devops/iso/新的/push_version.py new file mode 100644 index 00000000..41a9bead --- /dev/null +++ b/devops/iso/新的/push_version.py @@ -0,0 +1,402 @@ +#!/usr/bin/env python3 +import jwt +import time +import requests +import os +import sys +import datetime +from pathlib import Path + + +# ============================================== +# 重试配置参数(可按需修改) +# ============================================== +MAX_RETRIES = 10 # 查找构建的最大重试次数 +RETRY_DELAY = 30 # 查找构建的重试间隔(秒) +SUBMIT_INIT_WAIT = 60 # 提交前初始等待时间(秒) +SUBMIT_MAX_RETRIES = 20 # 提交审核的最大重试次数 +SUBMIT_BASE_DELAY = 30 # 提交审核的初始重试间隔(秒) +SUBMIT_DELAY_INCREMENT = 10 # 每次重试间隔递增(秒) + +# ============================================== +# 其他配置参数 +# ============================================== +def get_chinese_date_time(): + """ + 获取当前时间,以中文格式返回(如:8月5日 上午8点24分) + 包含月、日、上午/下午、时、分,不包含秒数 + """ + now = datetime.datetime.now() + month = now.month + day = now.day + hour_24 = now.hour + minute = now.minute + + if hour_24 < 12: + period = "上午" + hour_12 = hour_24 if hour_24 != 0 else 12 + else: + period = "下午" + hour_12 = hour_24 if hour_24 == 12 else hour_24 - 12 + + return f"{month}月{day}日 {period}{hour_12}点{minute}分" + + +# 获取参数 +if len(sys.argv) >= 2 and sys.argv[1]: + env_name = sys.argv[1] +else: + env_name = 'develop' + +if len(sys.argv) >= 3 and sys.argv[2]: + build_number_str = sys.argv[2] +else: + build_number_str = '68' + +# 验证第一个参数(枚举值) +valid_envs = ['develop', 'sit', 'uat'] +if env_name not in valid_envs: + print(f"错误:环境名称 '{env_name}' 无效") + print(f"有效环境名称:{', '.join(valid_envs)}") + sys.exit(1) + +# 验证第二个参数(数字字符串) +if not build_number_str.isdigit(): + print(f"错误:构建号 '{build_number_str}' 必须是纯数字字符串") + sys.exit(1) + +# 参数验证通过,继续处理 +TARGET_BUILD_NUMBER = build_number_str + +if env_name == 'develop': + BETA_GROUP_NAME = "外部自动化测试" + BETA_GROUP_NAME = "UAT" + TARGET_VERSION = "0.3.1" +elif env_name == 'sit': + BETA_GROUP_NAME = "SIT" + TARGET_VERSION = "0.2.1" +elif env_name == 'uat': + BETA_GROUP_NAME = "UAT" + TARGET_VERSION = "0.3.1" + +# 接收参数结束 + +# 配置参数 +API_KEY = "ACRB9XFL9G" +API_ISSUER = "69a6de7f-3378-47e3-e053-5b8c7c11a4d1" +APP_NAME = "吉AI学" +API_ENDPOINT = "https://api.appstoreconnect.apple.com/v1" + +if 'PYCHARM_HOSTED' in os.environ: + Auth_Key_Path = './' +else: + Auth_Key_Path = '/Users/jlbank/Desktop/lx_uniapp/auto_build' + +private_key_path = Path(f'{Auth_Key_Path}/AuthKey_{API_KEY}.p8') + +def generate_jwt_token(api_key, api_issuer, private_key_path): + """生成 JWT 令牌""" + with open(private_key_path, "r") as f: + private_key = f.read() + + current_time = int(time.time()) + payload = { + "iss": api_issuer, + "exp": current_time + 20 * 60, + "iat": current_time, + "aud": "appstoreconnect-v1" + } + + token = jwt.encode( + payload, + private_key, + algorithm="ES256", + headers={"kid": api_key} + ) + return token + + +def find_specific_build(app_id, headers): + """通过预发布版本ID查找指定构建版本,带重试机制""" + retries = 0 + + while retries < MAX_RETRIES: + try: + print(f"\n🔍 查找版本 {TARGET_VERSION} 构建号 {TARGET_BUILD_NUMBER} (尝试 {retries + 1}/{MAX_RETRIES})") + + print(" 正在获取预发布版本ID...") + pre_release_url = f"{API_ENDPOINT}/preReleaseVersions" + pre_release_params = { + "filter[version]": TARGET_VERSION, + "filter[app]": app_id + } + + pre_release_response = requests.get(pre_release_url, headers=headers, params=pre_release_params) + pre_release_response.raise_for_status() + pre_release_data = pre_release_response.json() + + if not pre_release_data["data"]: + print(f"❓ 未找到版本为 {TARGET_VERSION} 的预发布版本") + retries += 1 + if retries < MAX_RETRIES: + time.sleep(RETRY_DELAY) + continue + + pre_release_id = pre_release_data["data"][0]["id"] + print(f" 找到预发布版本ID: {pre_release_id}") + + builds_url = f"{API_ENDPOINT}/builds" + params = { + "filter[preReleaseVersion]": pre_release_id, + "sort": "-version", + "limit": "10", + "include": "buildBetaDetail,betaBuildLocalizations,preReleaseVersion,betaAppReviewSubmission,icons,buildBundles,betaGroups", + "limit[betaBuildLocalizations]": "40", + "limit[betaGroups]": "50" + } + + response = requests.get(builds_url, headers=headers, params=params) + + if response.status_code == 400: + print(f" 错误响应内容: {response.text}") + response.raise_for_status() + + builds_data = response.json() + + matching_builds = [ + b for b in builds_data["data"] + if b["attributes"].get("version") == TARGET_BUILD_NUMBER + ] + if not matching_builds: + print(f"❓ 未找到版本 {TARGET_VERSION} 构建号 {TARGET_BUILD_NUMBER} 的构建") + else: + valid_build = next(( + b for b in matching_builds + if b["attributes"]["processingState"] == "VALID" + ), None) + + if valid_build: + return valid_build + else: + states = [b["attributes"]["processingState"] for b in matching_builds] + print(f"⏳ 找到匹配的构建但状态为: {', '.join(states)},等待处理完成...") + + if retries < MAX_RETRIES - 1: + print(f"将在 {RETRY_DELAY} 秒后重试...") + time.sleep(RETRY_DELAY) + + retries += 1 + + except Exception as e: + print(f"查询过程中出错: {str(e)}") + retries += 1 + if retries < MAX_RETRIES: + time.sleep(RETRY_DELAY) + + return None + +# ============================================== +# 新增:带重试的提交审核函数 +# ============================================== +def submit_for_review_with_retry(build_id, headers): + """提交审核(带初始等待和动态递增间隔重试)""" + # 第一步:初始等待 + print(f"\n⌛ 提交审核前,先等待 {SUBMIT_INIT_WAIT} 秒(确保构建完全处理完成)...") + time.sleep(SUBMIT_INIT_WAIT) + + # 第二步:重试提交 + for retry in range(SUBMIT_MAX_RETRIES): + current_delay = SUBMIT_BASE_DELAY + (retry * SUBMIT_DELAY_INCREMENT) + try: + print(f"\n📋 提交构建版本审核 (尝试 {retry + 1}/{SUBMIT_MAX_RETRIES})") + print(f" 当前重试间隔:{current_delay} 秒") + + submit_url = f"{API_ENDPOINT}/betaAppReviewSubmissions" + submit_payload = { + "data": { + "type": "betaAppReviewSubmissions", + "relationships": { + "build": { + "data": {"id": build_id, "type": "builds"} + } + } + } + } + + submit_response = requests.post(submit_url, headers=headers, json=submit_payload) + submit_response.raise_for_status() + print("✅ 构建版本已成功提交审核") + return True # 提交成功,退出函数 + + except requests.exceptions.HTTPError as e: + # 处理已提交的情况(409冲突) + if submit_response.status_code == 409: + print("⚠️ 构建已提交审核,无需重复操作") + return True + else: + print(f"❌ 第 {retry + 1} 次提交审核失败: {e}") + print("错误详情:", submit_response.json()) + + # 最后一次重试失败则退出 + if retry == SUBMIT_MAX_RETRIES - 1: + print(f"\n❌ 已达到最大重试次数 ({SUBMIT_MAX_RETRIES}),提交审核失败") + return False + + # 非最后一次重试,等待后继续 + print(f" 将在 {current_delay} 秒后进行第 {retry + 2} 次重试...") + time.sleep(current_delay) + + except Exception as e: + print(f"❌ 第 {retry + 1} 次提交审核异常: {str(e)}") + + # 最后一次重试失败则退出 + if retry == SUBMIT_MAX_RETRIES - 1: + print(f"\n❌ 已达到最大重试次数 ({SUBMIT_MAX_RETRIES}),提交审核失败") + return False + + # 非最后一次重试,等待后继续 + print(f" 将在 {current_delay} 秒后进行第 {retry + 2} 次重试...") + time.sleep(current_delay) + + return False + +def main(): + try: + # 1. 生成 JWT 令牌 + if not private_key_path.exists(): + raise FileNotFoundError(f"私钥文件不存在: {private_key_path}") + + token = generate_jwt_token(API_KEY, API_ISSUER, private_key_path) + print("✅ JWT 令牌生成成功") + + # 2. 配置请求头 + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json" + } + + # 3. 获取应用 ID + print(f"\n🔍 查找应用: {APP_NAME}") + apps_url = f"{API_ENDPOINT}/apps" + response = requests.get(apps_url, headers=headers) + response.raise_for_status() + + apps_data = response.json() + app = next((a for a in apps_data["data"] if a["attributes"]["name"] == APP_NAME), None) + if not app: + raise ValueError(f"未找到应用: {APP_NAME}") + + app_id = app["id"] + print(f"✅ 找到应用 ID: {app_id}") + + # 4. 获取指定版本和构建号的构建版本(带重试) + valid_build = find_specific_build(app_id, headers) + if not valid_build: + raise ValueError( + f"经过 {MAX_RETRIES} 次尝试后,仍未找到可用的构建版本: {TARGET_VERSION} ({TARGET_BUILD_NUMBER})") + + build_id = valid_build["id"] + build_version = TARGET_VERSION + build_number = valid_build["attributes"]["version"] + print(f"✅ 找到构建版本 ID: {build_id} (版本号: {build_version}, 构建号: {build_number})") + + # 5. 获取外部测试群组 ID + print(f"\n🔍 查找测试群组: {BETA_GROUP_NAME}") + groups_url = f"{API_ENDPOINT}/betaGroups" + response = requests.get(groups_url, headers=headers) + response.raise_for_status() + + groups_data = response.json() + beta_group = next((g for g in groups_data["data"] if + g["attributes"]["name"] == BETA_GROUP_NAME and + g["attributes"]["isInternalGroup"] is False), None) + if not beta_group: + raise ValueError(f"未找到外部测试群组: {BETA_GROUP_NAME}") + + beta_group_id = beta_group["id"] + print(f"✅ 找到外部测试群组 ID: {beta_group_id}") + + # 6. 添加构建到测试群组后,更新测试内容(betaBuildLocalizations) + print("\n📝 更新测试版本的本地化信息(whatsNew)...") + + # 7. 将构建版本添加到测试群组 + print(f"\n🔗 将构建 {build_id} 添加到测试群组 {beta_group_id}...") + add_build_url = f"{API_ENDPOINT}/betaGroups/{beta_group_id}/relationships/builds" + + add_build_payload = { + "data": [{"id": build_id, "type": "builds"}] + } + + add_response = requests.post(add_build_url, headers=headers, json=add_build_payload) + try: + add_response.raise_for_status() + except requests.exceptions.HTTPError as e: + if add_response.status_code == 409: + print("⚠️ 构建已在测试群组中,跳过添加步骤") + else: + print(f"❌ 添加构建到测试群组失败: {e}") + print("错误详情:", add_response.json()) + sys.exit(1) + else: + print("✅ 构建已成功添加到测试群组") + + # 8. 更新测试内容(whatsNew) + get_localizations_url = f"{API_ENDPOINT}/builds/{build_id}/betaBuildLocalizations" + response = requests.get(get_localizations_url, headers=headers) + + try: + response.raise_for_status() + except requests.exceptions.HTTPError as e: + print(f"❌ 获取本地化信息失败: {e}") + print("错误详情:", response.json()) + sys.exit(1) + localizations = response.json().get("data", []) + + print("\n📝 更新测试版本说明...") + if localizations: + localization_id = localizations[0]["id"] + update_url = f"{API_ENDPOINT}/betaBuildLocalizations/{localization_id}" + print(f"使用现有本地化信息 ID: {localization_id}") + else: + print("创建新的本地化信息...") + create_url = f"{API_ENDPOINT}/betaBuildLocalizations" + create_payload = { + "data": { + "type": "betaBuildLocalizations", + "attributes": {"locale": "zh-Hans", "whatsNew": ""}, + "relationships": { + "build": {"data": {"id": build_id, "type": "builds"}} + } + } + } + create_response = requests.post(create_url, headers=headers, json=create_payload) + create_response.raise_for_status() + localization_id = create_response.json()["data"]["id"] + update_url = f"{API_ENDPOINT}/betaBuildLocalizations/{localization_id}" + + now_time_text = get_chinese_date_time() + update_payload = { + "data": { + "id": localization_id, + "type": "betaBuildLocalizations", + "attributes": { + "whatsNew": f"当前版本: {TARGET_BUILD_NUMBER}\n提交时间:{now_time_text}\n自动化提交" + } + } + } + update_response = requests.patch(update_url, headers=headers, json=update_payload) + update_response.raise_for_status() + print("✅ 测试版本说明已更新") + + # 9. 提交审核(调用新增的带重试函数) + submit_success = submit_for_review_with_retry(build_id, headers) + if not submit_success: + sys.exit(1) + + except Exception as e: + print(e) + exit(1) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/devops/iso/新的/ready_build_ios.sh b/devops/iso/新的/ready_build_ios.sh new file mode 100644 index 00000000..bfe3a24b --- /dev/null +++ b/devops/iso/新的/ready_build_ios.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# ============================================== +# 配置参数 - 请根据实际情况修改以下参数 +# ============================================== +# 钥匙串配置 +KEYCHAIN_PASSWORD="1234567" # 钥匙串密码 +KEYCHAIN_PATH="$HOME/Library/Keychains/login.keychain-db" # 钥匙串路径 + +# 项目路径配置 +PROJECT_DIR="$HOME/Desktop/lx_uniapp/build/git_work_code/Ios/HBuilder-Hello" # 项目目录 +PROJECT_NAME="HBuilder-Hello.xcodeproj" # Xcode项目文件名 +SCHEME_NAME="HBuilder" # 构建方案名称 +CONFIGURATION="Release" # 构建配置 + +# 构建输出配置 +BUILD_DIR="$HOME/Desktop/lx_uniapp/build" # 构建输出目录 +ARCHIVE_NAME="HBuilder.xcarchive" # 归档文件名 +IPA_DIR_NAME="ipa_production" # IPA输出目录名 +DERIVED_DATA_DIR="$HOME/Library/Developer/Xcode/DerivedData/*" # 衍生数据目录 + +# 版本配置 +MARKETING_VERSION="$1" # 市场版本号 +CURRENT_PROJECT_VERSION="$2" # 项目内部版本号 + +# 签名配置 +CODE_SIGN_IDENTITY="Apple Distribution: Bank of Jilin Co., Ltd. (2EP6SRRN43)" # 签名标识 +PROVISIONING_PROFILE="e3487fe1-19dc-4fc7-90df-11caf27da0c6" # 配置文件UUID +DEVELOPMENT_TEAM="2EP6SRRN43" # 开发团队ID +CODE_SIGNING_REQUIRED="YES" # 是否需要签名 + +# 导出配置 +EXPORT_OPTIONS_PLIST="$BUILD_DIR/ExportOptions_Production.plist" # 导出配置plist路径 +# ============================================== + +# 错误处理函数 +error_exit() { + echo "❌ $1" + exit 1 +} + +# 0. 解锁钥匙串并授予权限 +echo "🔑 解锁钥匙串..." +security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" || { + error_exit "钥匙串解锁失败" +} + +# 1. 进入项目目录 +echo "📂 进入项目目录: $PROJECT_DIR" +cd "$PROJECT_DIR" || { + error_exit "无法进入项目目录: $PROJECT_DIR" +} + +# 2. 清理旧构建 +echo "🧹 清理旧构建..." +xcodebuild -project "$PROJECT_NAME" -scheme "$SCHEME_NAME" -configuration "$CONFIGURATION" clean || { + error_exit "清理构建失败" +} + +# 3. 删除上次构建内容 +echo "🗑️ 删除上次构建内容..." +setopt rm_star_silent nullglob +rm -rf "$BUILD_DIR/$ARCHIVE_NAME" "$BUILD_DIR/$IPA_DIR_NAME" "$DERIVED_DATA_DIR" +unsetopt rm_star_silent nullglob # 恢复默认设置 + +# 4. 归档项目 +echo "📦 开始归档项目..." +xcodebuild -project "$PROJECT_NAME" \ + -scheme "$SCHEME_NAME" \ + -configuration "$CONFIGURATION" \ + -archivePath "$BUILD_DIR/$ARCHIVE_NAME" \ + MARKETING_VERSION="$MARKETING_VERSION" \ + CURRENT_PROJECT_VERSION="$CURRENT_PROJECT_VERSION" \ + -destination 'generic/platform=iOS' \ + CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" \ + PROVISIONING_PROFILE="$PROVISIONING_PROFILE" \ + DEVELOPMENT_TEAM="$DEVELOPMENT_TEAM" \ + CODE_SIGNING_REQUIRED="$CODE_SIGNING_REQUIRED" \ + OTHER_CFLAGS="" \ + OTHER_CPLUSPLUS_FLAGS="" \ + OTHER_SWIFT_FLAGS="" \ + archive || { + error_exit "项目归档失败" +} + +# 5. 导出IPA文件 +echo "📤 导出IPA文件..." +xcodebuild -exportArchive \ + -archivePath "$BUILD_DIR/$ARCHIVE_NAME" \ + -exportPath "$BUILD_DIR/$IPA_DIR_NAME" \ + -exportOptionsPlist "$EXPORT_OPTIONS_PLIST" || { + error_exit "IPA导出失败" +} + +echo "🎉 构建完成!IPA文件已导出至: $BUILD_DIR/$IPA_DIR_NAME" diff --git a/devops/iso/新的/show.py b/devops/iso/新的/show.py new file mode 100644 index 00000000..bf9570d0 --- /dev/null +++ b/devops/iso/新的/show.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +import os +import sys +print(f"🔍 当前脚本使用的 Python 路径:{sys.executable}") +print(f"🔍 当前 Python 环境变量 PATH:{os.environ.get('PATH')[:500]}...") # 只打印前500字符,避免过长 +print(f"🔍 当前 Conda 环境:{os.environ.get('CONDA_DEFAULT_ENV', '未激活 Conda 环境')}\n") \ No newline at end of file diff --git a/devops/iso/新的/sync_remote_branch.py b/devops/iso/新的/sync_remote_branch.py new file mode 100644 index 00000000..343d8767 --- /dev/null +++ b/devops/iso/新的/sync_remote_branch.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +import os +import subprocess +import sys + +# 颜色定义 +RED = '\033[0;31m' +GREEN = '\033[0;32m' +YELLOW = '\033[1;33m' +NC = '\033[0m' # 无颜色 + +def run_command(command, check=True, capture_output=False): + """执行系统命令并返回结果""" + try: + if capture_output: + result = subprocess.run( + command, + shell=True, + check=check, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + return result + else: + subprocess.run(command, shell=True, check=check) + return None + except subprocess.CalledProcessError as e: + print(f"{RED}错误:命令执行失败: {e}{NC}") + sys.exit(1) + +def main(): + # 检查参数 + if len(sys.argv) < 2: + print(f"{RED}错误:未传入分支名称参数!{NC}") + print(f"使用方法:{YELLOW}{sys.argv[0]} <远程分支名>{NC}") + sys.exit(1) + + print(f"▶ 先设置内网网络\n") + run_command("sudo route add -host 25.13.9.101 25.64.32.254") + + # 配置参数 + target_branch = sys.argv[1] + + # 关键修改:跨平台路径拼接(build + target_branch) + # 1. 获取脚本所在目录(作为相对路径基准,可选,根据实际需求调整) + script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) + parent_dir = os.path.dirname(script_dir) + # 2. 拼接路径:build/(相对脚本目录) + work_dir = os.path.join(parent_dir, "build", target_branch) + # 3. 转换为绝对路径(消除相对路径符号,更可靠) + work_dir = os.path.abspath(work_dir) + print(f"▶ 本地工作目录:{YELLOW}{work_dir}{NC}\n") + remote_name = "origin" + local_branch = "develop" + + print(f"\n{YELLOW}===== 开始执行分支同步脚本 ====={NC}") + print(f"▶ 远程目标分支:{YELLOW}{target_branch}{NC}") + + + # 1. 进入工作目录 + print(f"{YELLOW}1. 检查并进入工作目录...{NC}") + if not os.path.isdir(work_dir): + print(f"{RED}错误:工作目录不存在!{NC}") + sys.exit(1) + + try: + os.chdir(work_dir) + except OSError as e: + print(f"{RED}错误:无法进入工作目录!{e}{NC}") + sys.exit(1) + + print(f"✅ 成功进入工作目录:{os.getcwd()}\n") + + # 2. 检查Git仓库 + print(f"{YELLOW}2. 检查Git仓库...{NC}") + if not os.path.isdir(".git"): + print(f"{RED}错误:当前目录不是Git仓库!{NC}") + sys.exit(1) + print(f"✅ 确认是Git仓库\n") + + # 3. 关键修复:获取远程分支完整信息 + print(f"{YELLOW}3. 完整获取远程所有分支完整信息...{NC}") + # 完整拉取所有分支信息 + run_command(f"git fetch {remote_name} '+refs/heads/*:refs/remotes/{remote_name}/*'") + print(f"✅ 远程分支信息拉取完成\n") + + # 4. 验证远程分支是否存在 + print(f"{YELLOW}4. 验证远程 {target_branch} 分支...{NC}") + result = run_command( + f"git show-ref --verify --quiet 'refs/remotes/{remote_name}/{target_branch}'", + check=False, + capture_output=True + ) + + if result.returncode != 0: + print(f"{RED}错误:远程确实不存在 {target_branch} 分支!{NC}") + print("远程所有分支列表:") + run_command("git branch -r") + sys.exit(1) + + print(f"✅ 确认远程存在 {YELLOW}{target_branch}{NC} 分支\n") + + # 5. 同步到本地develop分支 + print(f"{YELLOW}5. 同步远程 {target_branch} 到本地 {local_branch}...{NC}") + print(f"{YELLOW}⚠️ 警告:将覆盖本地develop分支所有内容!{NC}") + + # 确保本地有develop分支 + run_command(f"git checkout -B {local_branch} >/dev/null 2>&1", check=False) + + # 关键命令:使用完整引用路径 + run_command(f"git reset --hard 'refs/remotes/{remote_name}/{target_branch}'") + + # 6. 完成提示 + print(f"\n{GREEN}===== 操作完成 ====={NC}") + print(f"✅ 本地 {YELLOW}{local_branch}{NC} 已同步为远程 {YELLOW}{target_branch}{NC} 最新状态") + print("当前版本:") + run_command("git log -1 --pretty=format:\"%h - %an, %ar : %s\"") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/devops/iso/新的/upload_to_appstore.py b/devops/iso/新的/upload_to_appstore.py new file mode 100644 index 00000000..166dceee --- /dev/null +++ b/devops/iso/新的/upload_to_appstore.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +import os +import subprocess +import sys +import tempfile + +# 颜色定义 +RED = '\033[0;31m' +GREEN = '\033[0;32m' +YELLOW = '\033[1;33m' +NC = '\033[0m' # 无颜色 + +def run_command(command, capture_output=False): + """执行系统命令并返回结果""" + try: + result = subprocess.run( + command, + shell=True, + check=True, + stdout=subprocess.PIPE if capture_output else None, + stderr=subprocess.STDOUT if capture_output else None, + text=True + ) + return result + except subprocess.CalledProcessError as e: + if capture_output: + return e # 返回错误信息供后续分析 + print(f"{RED}❌ 命令执行失败: {e.output}{NC}") + sys.exit(e.returncode) + +def main(): + # 检查参数 + if len(sys.argv) < 2: + print(f"{RED}错误:参数不足!{NC}") + print(f"使用方法:{YELLOW}{sys.argv[0]} {NC}") + print(f"示例:{YELLOW}{sys.argv[0]} sit{NC}") + sys.exit(1) + + # 解析参数(第一个参数为target_branch) + target_branch = sys.argv[1] + + # ============================================== + # 配置变量 - 根据实际情况修改以下参数 + # ============================================== + API_KEY = "ACRB9XFL9G" # App Store Connect API 密钥ID + API_ISSUER = "69a6de7f-3378-47e3-e053-5b8c7c11a4d1" # API 密钥对应的Issuer ID + APP_TYPE = "ios" # 应用类型(固定为ios) + + # 关键修改:根据target_branch拼接IPA路径 + build_dir = f"{os.path.expanduser('~')}/Desktop/lx_uniapp/build" # 构建输出目录 + ipa_dir_name = f"{target_branch}_ipa_production" # 带分支名的IPA目录 + IPA_PATH = os.path.join(build_dir, ipa_dir_name, "HBuilder.ipa") # 固定IPA文件名 + + # 显示参数信息 + print(f"{YELLOW}===== 上传配置信息 ====={NC}") + print(f"▶ 目标分支: {YELLOW}{target_branch}{NC}") + print(f"▶ IPA文件路径: {YELLOW}{IPA_PATH}{NC}\n") + + # ============================================== + # 验证IPA文件是否存在 + # ============================================== + if not os.path.isfile(IPA_PATH): + print(f"{RED}❌ 错误:未找到IPA文件!{NC}") + print(f" 查找路径:{IPA_PATH}") + print(f" 请确认该分支已成功构建IPA文件") + sys.exit(1) + + # ============================================== + # 1. 验证IPA文件合法性 + # ============================================== + print(f"{YELLOW}📋 开始验证IPA文件...{NC}") + print(f" 文件路径:{IPA_PATH}") + + # 创建临时文件保存输出 + with tempfile.NamedTemporaryFile(mode='w+', delete=False) as tmp_file: + tmp_filename = tmp_file.name + + # 执行验证命令 + validate_cmd = ( + f"xcrun altool --validate-app " + f"--type '{APP_TYPE}' " + f"--file '{IPA_PATH}' " + f"--apiKey '{API_KEY}' " + f"--apiIssuer '{API_ISSUER}' > '{tmp_filename}' 2>&1" + ) + + # 执行命令但不立即退出(需要处理特定错误) + result = run_command(validate_cmd, capture_output=True) + + # 读取并显示验证输出 + with open(tmp_filename, 'r') as f: + validate_output = f.read() + print(validate_output) + os.unlink(tmp_filename) # 清理临时文件 + + # 处理验证结果 + if isinstance(result, subprocess.CalledProcessError): + # 检查是否是版本号重复错误 + if "The bundle version must be higher than the previously uploaded version" in validate_output: + # 提取之前的版本号 + previous_version = None + if "previousBundleVersion = " in validate_output: + previous_version = validate_output.split("previousBundleVersion = ")[1].split()[0] + elif "version: ‘" in validate_output: + previous_version = validate_output.split("version: ‘")[1].split("’")[0] + + print(f"{RED}❌ 错误:版本号重复{NC}") + if previous_version: + print(f"{RED} 已上传的最新版本号为: {previous_version}{NC}") + try: + print(f"{RED} 请将版本号修改为 {int(previous_version) + 1} 或更高后重试{NC}") + except ValueError: + print(f"{RED} 请将版本号修改为更高版本后重试{NC}") + else: + print(f"{RED} 请将版本号修改为更高版本后重试{NC}") + sys.exit(result.returncode) + else: + print(f"{RED}❌ IPA文件验证失败,请查看上方错误信息{NC}") + sys.exit(result.returncode) + else: + print(f"{GREEN}✅ IPA文件验证成功,符合上传要求{NC}") + + # ============================================== + # 2. 上传IPA文件到App Store Connect + # ============================================== + print(f"\n{YELLOW}🚀 开始上传IPA文件...{NC}") + print(f" 文件路径:{IPA_PATH}") + + upload_cmd = ( + f"xcrun altool --upload-app " + f"--type '{APP_TYPE}' " + f"--file '{IPA_PATH}' " + f"--apiKey '{API_KEY}' " + f"--apiIssuer '{API_ISSUER}'" + ) + + run_command(upload_cmd) + + # 上传成功提示 + print(f"\n{GREEN}🎉 上传成功!可在App Store Connect中查看构建版本{NC}") + print(f" 提示:构建版本处理需要几分钟,请耐心等待") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/devops/iso/新的/validate_and_upload.sh b/devops/iso/新的/validate_and_upload.sh new file mode 100644 index 00000000..5bcab95d --- /dev/null +++ b/devops/iso/新的/validate_and_upload.sh @@ -0,0 +1,92 @@ +#!/bin/bash +set -e # 脚本执行过程中若有命令失败则立即退出 + +# ============================================== +# 颜色定义 +# ============================================== +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # 无颜色(重置) + +# ============================================== +# 配置变量 - 根据实际情况修改以下参数 +# ============================================== +API_KEY="ACRB9XFL9G" # App Store Connect API 密钥ID +API_ISSUER="69a6de7f-3378-47e3-e053-5b8c7c11a4d1" # API 密钥对应的Issuer ID +IPA_PATH="$HOME/Desktop/lx_uniapp/build/ipa_production/HBuilder.ipa" # IPA文件路径 +APP_TYPE="ios" # 应用类型(固定为ios) + +# ============================================== +# 验证IPA文件是否存在 +# ============================================== +if [ ! -f "$IPA_PATH" ]; then + echo -e "${RED}❌ 错误:未找到IPA文件,请检查路径是否正确${NC}" + echo -e " 查找路径:$IPA_PATH" + exit 1 +fi +# ============================================== +# 1. 验证IPA文件合法性 +# ============================================== +echo -e "\n${YELLOW}📋 开始验证IPA文件...${NC}" +echo -e " 文件路径:$IPA_PATH" + +# 创建临时文件保存输出 +TMP_FILE=$(mktemp) + +# 执行验证命令,直接输出到终端,同时重定向到临时文件 +xcrun altool --validate-app \ + --type "$APP_TYPE" \ + --file "$IPA_PATH" \ + --apiKey "$API_KEY" \ + --apiIssuer "$API_ISSUER" > "$TMP_FILE" 2>&1 +# 直接打印临时文件内容(确保错误信息显示) +cat "$TMP_FILE" + +# 获取退出码 +VALIDATE_EXIT_CODE=$? + +# 从临时文件读取内容用于分析 +VALIDATE_OUTPUT=$(cat "$TMP_FILE") +rm "$TMP_FILE" # 清理临时文件 + +# 验证结果处理 +if [ $VALIDATE_EXIT_CODE -eq 0 ]; then + echo -e "${GREEN}✅ IPA文件验证成功,符合上传要求${NC}" +else + # 检查是否是版本号重复错误 + if echo "$VALIDATE_OUTPUT" | grep -q "The bundle version must be higher than the previously uploaded version"; then + # 提取之前的版本号 + PREVIOUS_VERSION=$(echo "$VALIDATE_OUTPUT" | grep -oE 'previousBundleVersion = [0-9]+' | awk '{print $3}') + if [ -z "$PREVIOUS_VERSION" ]; then + PREVIOUS_VERSION=$(echo "$VALIDATE_OUTPUT" | grep -oE 'version: ‘[0-9]+’' | sed "s/version: ‘//;s/’//") + fi + + echo -e "${RED}❌ 错误:版本号重复${NC}" + echo -e "${RED} 已上传的最新版本号为: $PREVIOUS_VERSION${NC}" + echo -e "${RED} 请将版本号修改为 $((PREVIOUS_VERSION + 1)) 或更高后重试${NC}" + else + echo -e "${RED}❌ IPA文件验证失败,请查看上方错误信息${NC}" + fi + exit $VALIDATE_EXIT_CODE +fi +# ============================================== +# 2. 上传IPA文件到App Store Connect +# ============================================== +echo -e "\n${YELLOW}🚀 开始上传IPA文件...${NC}" +echo -e " 文件路径:$IPA_PATH" + +xcrun altool --upload-app \ + --type "$APP_TYPE" \ + --file "$IPA_PATH" \ + --apiKey "$API_KEY" \ + --apiIssuer "$API_ISSUER" + +# 上传成功提示 +if [ $? -eq 0 ]; then + echo -e "\n${GREEN}🎉 上传成功!可在App Store Connect中查看构建版本${NC}" + echo -e " 提示:构建版本处理需要几分钟,请耐心等待" +else + echo -e "\n${RED}❌ 上传失败,请根据错误信息修复后重试${NC}" + exit 1 +fi diff --git a/devops/iso/老的/AuthKey_ACRB9XFL9G.p8 b/devops/iso/老的/AuthKey_ACRB9XFL9G.p8 new file mode 100644 index 00000000..c209d906 --- /dev/null +++ b/devops/iso/老的/AuthKey_ACRB9XFL9G.p8 @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgZfELkUrcpqqAVlQg +UfKNlPbySAnafYL+vEndTe9/xoqgCgYIKoZIzj0DAQehRANCAATBz1/RZd+1AEgU +VfnoB1PNUMynS8FQ/zJdTcZ25qEuu6WVkWb82Ltmb1lIRSZpRWEbpQzL+7X6zQ95 +yjRmUksW +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/devops/iso/老的/git_update_remote.sh b/devops/iso/老的/git_update_remote.sh new file mode 100644 index 00000000..8c7947db --- /dev/null +++ b/devops/iso/老的/git_update_remote.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# 脚本名称:sync_remote_branch.sh +# 功能描述:修复origin/sit引用问题,强制同步远程分支到本地develop +# 使用方法:./sync_remote_branch.sh <远程分支名> + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# 检查参数 +if [ $# -eq 0 ]; then + echo -e "${RED}错误:未传入分支名称参数!${NC}" + echo -e "使用方法:${YELLOW}$0 <远程分支名>${NC}" + exit 1 +fi +echo -e "▶ 先设置内网网络\n" +sudo route add -host 25.13.9.101 25.64.32.254 +# 配置参数 +TARGET_BRANCH="$1" +WORK_DIR="Desktop/lx_uniapp/build/git_work_code" +REMOTE_NAME="origin" +LOCAL_BRANCH="develop" + +echo -e "\n${YELLOW}===== 开始执行分支同步脚本 =====${NC}" +echo -e "▶ 远程目标分支:${YELLOW}${TARGET_BRANCH}${NC}" +echo -e "▶ 本地工作目录:${YELLOW}${WORK_DIR}${NC}\n" + +# 1. 进入工作目录 +echo -e "${YELLOW}1. 检查并进入工作目录...${NC}" +if [ ! -d "$WORK_DIR" ]; then + echo -e "${RED}错误:工作目录不存在!${NC}" + exit 1 +fi +cd "$WORK_DIR" || { + echo -e "${RED}错误:无法进入工作目录!${NC}" + exit 1 +} +echo -e "✅ 成功进入工作目录:$(pwd)\n" + +# 2. 检查Git仓库 +echo -e "${YELLOW}2. 检查Git仓库...${NC}" +if [ ! -d ".git" ]; then + echo -e "${RED}错误:当前目录不是Git仓库!${NC}" + exit 1 +fi +echo -e "✅ 确认是Git仓库\n" + +# 3. 关键修复:获取远程分支完整信息(不限制深度) +echo -e "${YELLOW}3. 完整获取远程所有分支完整信息...${NC}" +# 先移除可能存在的浅层克隆限制 +git config --unset core.depth +# 完整拉取所有分支信息 +if ! git fetch "$REMOTE_NAME" "+refs/heads/*:refs/remotes/$REMOTE_NAME/*"; then + echo -e "${RED}错误:拉取远程分支信息失败!${NC}" + exit 1 +fi +echo -e "✅ 远程分支信息拉取完成\n" + +# 4. 再次检查远程分支是否存在 +echo -e "${YELLOW}4. 验证远程 ${TARGET_BRANCH} 分支...${NC}" +if ! git show-ref --verify --quiet "refs/remotes/$REMOTE_NAME/$TARGET_BRANCH"; then + echo -e "${RED}错误:远程确实不存在 ${TARGET_BRANCH} 分支!${NC}" + echo -e "远程所有分支列表:" + git branch -r + exit 1 +fi +echo -e "✅ 确认远程存在 ${YELLOW}${TARGET_BRANCH}${NC} 分支\n" + +# 5. 同步到本地develop分支 +echo -e "${YELLOW}5. 同步远程 ${TARGET_BRANCH} 到本地 ${LOCAL_BRANCH}...${NC}" +echo -e "${YELLOW}⚠️ 警告:将覆盖本地develop分支所有内容!${NC}" + +# 确保本地有develop分支 +git checkout -B "$LOCAL_BRANCH" >/dev/null 2>&1 + +# 关键命令:使用完整引用路径 +if ! git reset --hard "refs/remotes/$REMOTE_NAME/$TARGET_BRANCH"; then + echo -e "${RED}错误:同步远程分支到本地失败!${NC}" + exit 1 +fi + +# 6. 完成提示 +echo -e "\n${GREEN}===== 操作完成 =====${NC}" +echo -e "✅ 本地 ${YELLOW}${LOCAL_BRANCH}${NC} 已同步为远程 ${YELLOW}${TARGET_BRANCH}${NC} 最新状态" +echo -e "当前版本:" +git log -1 --pretty=format:"%h - %an, %ar : %s" diff --git a/devops/iso/老的/push_version.py b/devops/iso/老的/push_version.py new file mode 100644 index 00000000..d9a35e82 --- /dev/null +++ b/devops/iso/老的/push_version.py @@ -0,0 +1,382 @@ +import jwt +import time +import requests +import os +import sys +import datetime +from pathlib import Path + + +def get_chinese_date_time(): + """ + 获取当前时间,以中文格式返回(如:8月5日 上午8点24分) + 包含月、日、上午/下午、时、分,不包含秒数 + """ + # 获取当前时间 + now = datetime.datetime.now() + + # 获取月份和日期 + month = now.month + day = now.day + + # 获取24小时制小时数和分钟数 + hour_24 = now.hour + minute = now.minute + + # 确定上午/下午 + if hour_24 < 12: + period = "上午" + # 转换为12小时制(0点特殊处理为12点) + hour_12 = hour_24 if hour_24 != 0 else 12 + else: + period = "下午" + # 转换为12小时制(12点保持12点,13点及以后减12) + hour_12 = hour_24 if hour_24 == 12 else hour_24 - 12 + + # 格式化返回字符串 + return f"{month}月{day}日 {period}{hour_12}点{minute}分" + + +# 获取参数 +# 处理第一个参数(环境),默认值为'develop' +if len(sys.argv) >= 2 and sys.argv[1]: + env_name = sys.argv[1] +else: + env_name = 'develop' + +# 处理第二个参数(构建号),默认值为'2' +if len(sys.argv) >= 3 and sys.argv[2]: + build_number_str = sys.argv[2] +else: + build_number_str = '68' + +# 验证第一个参数(枚举值) +valid_envs = ['develop', 'sit', 'uat'] +if env_name not in ['develop', 'sit', 'uat']: + print(f"错误:环境名称 '{env_name}' 无效有效") + print(f"有效环境名称:{', '.join(valid_envs)}") + sys.exit(1) + +# 验证第二个参数(数字字符串) +if not build_number_str.isdigit(): + print(f"错误:构建号 '{build_number_str}' 必须是纯数字字符串") + sys.exit(1) + +# 参数验证通过,继续处理 +TARGET_BUILD_NUMBER = build_number_str + +if env_name == 'develop': + BETA_GROUP_NAME = "外部自动化测试" # 测试群组 + BETA_GROUP_NAME = "UAT" # 测试群组 + TARGET_VERSION = "0.3.1" +elif env_name == 'sit': + BETA_GROUP_NAME = "SIT" + TARGET_VERSION = "0.2.1" +elif env_name == 'uat': + BETA_GROUP_NAME = "UAT" + TARGET_VERSION = "0.3.1" + +# 接收参数结束 + +# 配置参数 +API_KEY = "ACRB9XFL9G" +API_ISSUER = "69a6de7f-3378-47e3-e053-5b8c7c11a4d1" +APP_NAME = "吉AI学" # 应用名称 +API_ENDPOINT = "https://api.appstoreconnect.apple.com/v1" + + + +MAX_RETRIES = 10 # 最大重试次数 +RETRY_DELAY = 30 # 重试间隔(秒) +if 'PYCHARM_HOSTED' in os.environ: # 说明是pycharm + Auth_Key_Path = './' +else: + Auth_Key_Path = '/Users/jlbank/Desktop/lx_uniapp/auto_build' # p8私钥文件位置 + +private_key_path = Path(f'{Auth_Key_Path}/AuthKey_{API_KEY}.p8') + +def generate_jwt_token(api_key, api_issuer, private_key_path): + """生成 JWT 令牌""" + with open(private_key_path, "r") as f: + private_key = f.read() + + # 令牌有效期 20 分钟 + current_time = int(time.time()) + payload = { + "iss": api_issuer, + "exp": current_time + 20 * 60, + "iat": current_time, + "aud": "appstoreconnect-v1" + } + + # 生成 JWT 令牌 + token = jwt.encode( + payload, + private_key, + algorithm="ES256", + headers={"kid": api_key} + ) + return token + + +def find_specific_build(app_id, headers): + """通过预发布版本ID查找指定构建版本,带重试机制""" + retries = 0 + + while retries < MAX_RETRIES: + try: + print(f"\n🔍 查找版本 {TARGET_VERSION} 构建号 {TARGET_BUILD_NUMBER} (尝试 {retries + 1}/{MAX_RETRIES})") + + # 1. 先获取目标版本对应的预发布版本ID + print(" 正在获取预发布版本ID...") + pre_release_url = f"{API_ENDPOINT}/preReleaseVersions" + pre_release_params = { + "filter[version]": TARGET_VERSION, + "filter[app]": app_id + } + + pre_release_response = requests.get(pre_release_url, headers=headers, params=pre_release_params) + pre_release_response.raise_for_status() + pre_release_data = pre_release_response.json() + + if not pre_release_data["data"]: + print(f"❓ 未找到版本为 {TARGET_VERSION} 的预发布版本") + retries += 1 + if retries < MAX_RETRIES: + time.sleep(RETRY_DELAY) + continue + + pre_release_id = pre_release_data["data"][0]["id"] + print(f" 找到预发布版本ID: {pre_release_id}") + + # 2. 使用预发布版本ID筛选构建版本(修正参数错误) + builds_url = f"{API_ENDPOINT}/builds" + params = { + "filter[preReleaseVersion]": pre_release_id, + "sort": "-version", + "limit": "10", + # 移除了无效的ciBuildGroup关联 + "include": "buildBetaDetail,betaBuildLocalizations,preReleaseVersion,betaAppReviewSubmission,icons,buildBundles,betaGroups", + # 移除了无效的ciBuildGroups字段 + "limit[betaBuildLocalizations]": "40", + # 将betaGroups的limit调整为最大值50 + "limit[betaGroups]": "50" + } + + response = requests.get(builds_url, headers=headers, params=params) + + if response.status_code == 400: + print(f" 错误响应内容: {response.text}") + response.raise_for_status() + + builds_data = response.json() + + # 在返回结果中筛选出符合构建号的构建 + matching_builds = [ + b for b in builds_data["data"] + if b["attributes"].get("version") == TARGET_BUILD_NUMBER + ] + if not matching_builds: + print(f"❓ 未找到版本 {TARGET_VERSION} 构建号 {TARGET_BUILD_NUMBER} 的构建") + else: + # 检查是否有状态为VALID的构建 + valid_build = next(( + b for b in matching_builds + if b["attributes"]["processingState"] == "VALID" + ), None) + + if valid_build: + return valid_build + else: + # 显示找到的构建但状态不是VALID + states = [b["attributes"]["processingState"] for b in matching_builds] + print(f"⏳ 找到匹配的构建但状态为: {', '.join(states)},等待处理完成...") + + # 重试前等待 + if retries < MAX_RETRIES - 1: + print(f"将在 {RETRY_DELAY} 秒后重试...") + time.sleep(RETRY_DELAY) + + retries += 1 + + except Exception as e: + print(f"查询过程中出错: {str(e)}") + retries += 1 + if retries < MAX_RETRIES: + time.sleep(RETRY_DELAY) + + return None +def main(): + try: + # 1. 生成 JWT 令牌 + + if not private_key_path.exists(): + raise FileNotFoundError(f"私钥文件不存在: {private_key_path}") + + token = generate_jwt_token(API_KEY, API_ISSUER, private_key_path) + print("✅ JWT 令牌生成成功") + + # 2. 配置请求头 + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json" + } + + # 3. 获取应用 ID + print(f"\n🔍 查找应用: {APP_NAME}") + apps_url = f"{API_ENDPOINT}/apps" + response = requests.get(apps_url, headers=headers) + response.raise_for_status() + + apps_data = response.json() + app = next((a for a in apps_data["data"] if a["attributes"]["name"] == APP_NAME), None) + if not app: + raise ValueError(f"未找到应用: {APP_NAME}") + + app_id = app["id"] + print(f"✅ 找到应用 ID: {app_id}") + + # 4. 获取指定版本和构建号的构建版本(带重试) + valid_build = find_specific_build(app_id, headers) + if not valid_build: + raise ValueError( + f"经过 {MAX_RETRIES} 次尝试后,仍未找到可用的构建版本: {TARGET_VERSION} ({TARGET_BUILD_NUMBER})") + + build_id = valid_build["id"] + build_version = TARGET_VERSION + build_number = valid_build["attributes"]["version"] + print(f"✅ 找到构建版本 ID: {build_id} (版本号: {build_version}, 构建号: {build_number})") + + # 5. 获取外部测试群组 ID + print(f"\n🔍 查找测试群组: {BETA_GROUP_NAME}") + groups_url = f"{API_ENDPOINT}/betaGroups" + response = requests.get(groups_url, headers=headers) + response.raise_for_status() + + groups_data = response.json() + beta_group = next((g for g in groups_data["data"] if + g["attributes"]["name"] == BETA_GROUP_NAME and + g["attributes"]["isInternalGroup"] is False), None) # 确保是外部群组 + if not beta_group: + raise ValueError(f"未找到外部测试群组: {BETA_GROUP_NAME}") + + beta_group_id = beta_group["id"] + print(f"✅ 找到外部测试群组 ID: {beta_group_id}") + + # 6. 添加构建到测试群组后,更新测试内容(betaBuildLocalizations) + print("\n📝 更新测试版本的本地化信息(whatsNew)...") + + # 7. 将构建版本添加到测试群组 + print(f"\n🔗 将构建 {build_id} 添加到测试群组 {beta_group_id}...") + add_build_url = f"{API_ENDPOINT}/betaGroups/{beta_group_id}/relationships/builds" + + # 准备添加构建的请求数据 + add_build_payload = { + "data": [{"id": build_id, "type": "builds"}] + } + + # 发送添加请求 + add_response = requests.post(add_build_url, headers=headers, json=add_build_payload) + try: + add_response.raise_for_status() + except requests.exceptions.HTTPError as e: + # 处理已存在的情况(409 Conflict 是正常现象,说明已添加) + if add_response.status_code == 409: + print("⚠️ 构建已在测试群组中,跳过添加步骤") + else: + print(f"❌ 添加构建到测试群组失败: {e}") + print("错误详情:", add_response.json()) + sys.exit(1) + else: + print("✅ 构建已成功添加到测试群组") + # 8. 更新测试内容(whatsNew) + # 先获取该构建的本地化信息 ID(如果已有) + # 构建 ID(build_id 是你要操作的构建版本 ID) + get_localizations_url = f"{API_ENDPOINT}/builds/{build_id}/betaBuildLocalizations" + response = requests.get(get_localizations_url, headers=headers) + + try: + response.raise_for_status() + except requests.exceptions.HTTPError as e: + print(f"❌ 获取本地化信息失败: {e}") + print("错误详情:", response.json()) + sys.exit(1) + localizations = response.json().get("data", []) + + print("\n📝 更新测试版本说明...") + if localizations: + # 使用现有本地化信息 + localization_id = localizations[0]["id"] + update_url = f"{API_ENDPOINT}/betaBuildLocalizations/{localization_id}" + print(f"使用现有本地化信息 ID: {localization_id}") + else: + # 创建新的本地化信息(默认简体中文) + print("创建新的本地化信息...") + create_url = f"{API_ENDPOINT}/betaBuildLocalizations" + create_payload = { + "data": { + "type": "betaBuildLocalizations", + "attributes": {"locale": "zh-Hans", "whatsNew": ""}, + "relationships": { + "build": {"data": {"id": build_id, "type": "builds"}} + } + } + } + create_response = requests.post(create_url, headers=headers, json=create_payload) + create_response.raise_for_status() + localization_id = create_response.json()["data"]["id"] + update_url = f"{API_ENDPOINT}/betaBuildLocalizations/{localization_id}" + now_time_text = get_chinese_date_time() + # 更新测试内容 + update_payload = { + "data": { + "id": localization_id, + "type": "betaBuildLocalizations", + "attributes": { + "whatsNew": f"当前版本: {TARGET_BUILD_NUMBER}\n提交时间:{now_time_text}\n自动化提交" + } + } + } + update_response = requests.patch(update_url, headers=headers, json=update_payload) + update_response.raise_for_status() + print("✅ 测试版本说明已更新") + + # 9. 提交审核(触发测试状态)- 修复API端点 + print("\n📋 提交构建版本审核...") + + # 正确的提交审核API端点 + submit_url = f"{API_ENDPOINT}/betaAppReviewSubmissions" + submit_payload = { + "data": { + "type": "betaAppReviewSubmissions", + "relationships": { + "build": { + "data": {"id": build_id, "type": "builds"} + } + } + } + } + + submit_response = requests.post(submit_url, headers=headers, json=submit_payload) + try: + submit_response.raise_for_status() + except requests.exceptions.HTTPError as e: + # 处理已提交的情况(409冲突) + if submit_response.status_code == 409: + print("⚠️ 构建已提交审核,无需重复操作") + else: + print(f"❌ 提交审核失败: {e}") + print("错误详情:", submit_response.json()) + sys.exit(1) + else: + print("✅ 构建版本已成功提交审核") + + + except Exception as e: + print(e) + exit(1) + + +if __name__ == "__main__": + + main() \ No newline at end of file diff --git a/devops/iso/老的/ready_build_ios.sh b/devops/iso/老的/ready_build_ios.sh new file mode 100644 index 00000000..bfe3a24b --- /dev/null +++ b/devops/iso/老的/ready_build_ios.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# ============================================== +# 配置参数 - 请根据实际情况修改以下参数 +# ============================================== +# 钥匙串配置 +KEYCHAIN_PASSWORD="1234567" # 钥匙串密码 +KEYCHAIN_PATH="$HOME/Library/Keychains/login.keychain-db" # 钥匙串路径 + +# 项目路径配置 +PROJECT_DIR="$HOME/Desktop/lx_uniapp/build/git_work_code/Ios/HBuilder-Hello" # 项目目录 +PROJECT_NAME="HBuilder-Hello.xcodeproj" # Xcode项目文件名 +SCHEME_NAME="HBuilder" # 构建方案名称 +CONFIGURATION="Release" # 构建配置 + +# 构建输出配置 +BUILD_DIR="$HOME/Desktop/lx_uniapp/build" # 构建输出目录 +ARCHIVE_NAME="HBuilder.xcarchive" # 归档文件名 +IPA_DIR_NAME="ipa_production" # IPA输出目录名 +DERIVED_DATA_DIR="$HOME/Library/Developer/Xcode/DerivedData/*" # 衍生数据目录 + +# 版本配置 +MARKETING_VERSION="$1" # 市场版本号 +CURRENT_PROJECT_VERSION="$2" # 项目内部版本号 + +# 签名配置 +CODE_SIGN_IDENTITY="Apple Distribution: Bank of Jilin Co., Ltd. (2EP6SRRN43)" # 签名标识 +PROVISIONING_PROFILE="e3487fe1-19dc-4fc7-90df-11caf27da0c6" # 配置文件UUID +DEVELOPMENT_TEAM="2EP6SRRN43" # 开发团队ID +CODE_SIGNING_REQUIRED="YES" # 是否需要签名 + +# 导出配置 +EXPORT_OPTIONS_PLIST="$BUILD_DIR/ExportOptions_Production.plist" # 导出配置plist路径 +# ============================================== + +# 错误处理函数 +error_exit() { + echo "❌ $1" + exit 1 +} + +# 0. 解锁钥匙串并授予权限 +echo "🔑 解锁钥匙串..." +security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" || { + error_exit "钥匙串解锁失败" +} + +# 1. 进入项目目录 +echo "📂 进入项目目录: $PROJECT_DIR" +cd "$PROJECT_DIR" || { + error_exit "无法进入项目目录: $PROJECT_DIR" +} + +# 2. 清理旧构建 +echo "🧹 清理旧构建..." +xcodebuild -project "$PROJECT_NAME" -scheme "$SCHEME_NAME" -configuration "$CONFIGURATION" clean || { + error_exit "清理构建失败" +} + +# 3. 删除上次构建内容 +echo "🗑️ 删除上次构建内容..." +setopt rm_star_silent nullglob +rm -rf "$BUILD_DIR/$ARCHIVE_NAME" "$BUILD_DIR/$IPA_DIR_NAME" "$DERIVED_DATA_DIR" +unsetopt rm_star_silent nullglob # 恢复默认设置 + +# 4. 归档项目 +echo "📦 开始归档项目..." +xcodebuild -project "$PROJECT_NAME" \ + -scheme "$SCHEME_NAME" \ + -configuration "$CONFIGURATION" \ + -archivePath "$BUILD_DIR/$ARCHIVE_NAME" \ + MARKETING_VERSION="$MARKETING_VERSION" \ + CURRENT_PROJECT_VERSION="$CURRENT_PROJECT_VERSION" \ + -destination 'generic/platform=iOS' \ + CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" \ + PROVISIONING_PROFILE="$PROVISIONING_PROFILE" \ + DEVELOPMENT_TEAM="$DEVELOPMENT_TEAM" \ + CODE_SIGNING_REQUIRED="$CODE_SIGNING_REQUIRED" \ + OTHER_CFLAGS="" \ + OTHER_CPLUSPLUS_FLAGS="" \ + OTHER_SWIFT_FLAGS="" \ + archive || { + error_exit "项目归档失败" +} + +# 5. 导出IPA文件 +echo "📤 导出IPA文件..." +xcodebuild -exportArchive \ + -archivePath "$BUILD_DIR/$ARCHIVE_NAME" \ + -exportPath "$BUILD_DIR/$IPA_DIR_NAME" \ + -exportOptionsPlist "$EXPORT_OPTIONS_PLIST" || { + error_exit "IPA导出失败" +} + +echo "🎉 构建完成!IPA文件已导出至: $BUILD_DIR/$IPA_DIR_NAME" diff --git a/devops/iso/老的/validate_and_upload.sh b/devops/iso/老的/validate_and_upload.sh new file mode 100644 index 00000000..5bcab95d --- /dev/null +++ b/devops/iso/老的/validate_and_upload.sh @@ -0,0 +1,92 @@ +#!/bin/bash +set -e # 脚本执行过程中若有命令失败则立即退出 + +# ============================================== +# 颜色定义 +# ============================================== +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # 无颜色(重置) + +# ============================================== +# 配置变量 - 根据实际情况修改以下参数 +# ============================================== +API_KEY="ACRB9XFL9G" # App Store Connect API 密钥ID +API_ISSUER="69a6de7f-3378-47e3-e053-5b8c7c11a4d1" # API 密钥对应的Issuer ID +IPA_PATH="$HOME/Desktop/lx_uniapp/build/ipa_production/HBuilder.ipa" # IPA文件路径 +APP_TYPE="ios" # 应用类型(固定为ios) + +# ============================================== +# 验证IPA文件是否存在 +# ============================================== +if [ ! -f "$IPA_PATH" ]; then + echo -e "${RED}❌ 错误:未找到IPA文件,请检查路径是否正确${NC}" + echo -e " 查找路径:$IPA_PATH" + exit 1 +fi +# ============================================== +# 1. 验证IPA文件合法性 +# ============================================== +echo -e "\n${YELLOW}📋 开始验证IPA文件...${NC}" +echo -e " 文件路径:$IPA_PATH" + +# 创建临时文件保存输出 +TMP_FILE=$(mktemp) + +# 执行验证命令,直接输出到终端,同时重定向到临时文件 +xcrun altool --validate-app \ + --type "$APP_TYPE" \ + --file "$IPA_PATH" \ + --apiKey "$API_KEY" \ + --apiIssuer "$API_ISSUER" > "$TMP_FILE" 2>&1 +# 直接打印临时文件内容(确保错误信息显示) +cat "$TMP_FILE" + +# 获取退出码 +VALIDATE_EXIT_CODE=$? + +# 从临时文件读取内容用于分析 +VALIDATE_OUTPUT=$(cat "$TMP_FILE") +rm "$TMP_FILE" # 清理临时文件 + +# 验证结果处理 +if [ $VALIDATE_EXIT_CODE -eq 0 ]; then + echo -e "${GREEN}✅ IPA文件验证成功,符合上传要求${NC}" +else + # 检查是否是版本号重复错误 + if echo "$VALIDATE_OUTPUT" | grep -q "The bundle version must be higher than the previously uploaded version"; then + # 提取之前的版本号 + PREVIOUS_VERSION=$(echo "$VALIDATE_OUTPUT" | grep -oE 'previousBundleVersion = [0-9]+' | awk '{print $3}') + if [ -z "$PREVIOUS_VERSION" ]; then + PREVIOUS_VERSION=$(echo "$VALIDATE_OUTPUT" | grep -oE 'version: ‘[0-9]+’' | sed "s/version: ‘//;s/’//") + fi + + echo -e "${RED}❌ 错误:版本号重复${NC}" + echo -e "${RED} 已上传的最新版本号为: $PREVIOUS_VERSION${NC}" + echo -e "${RED} 请将版本号修改为 $((PREVIOUS_VERSION + 1)) 或更高后重试${NC}" + else + echo -e "${RED}❌ IPA文件验证失败,请查看上方错误信息${NC}" + fi + exit $VALIDATE_EXIT_CODE +fi +# ============================================== +# 2. 上传IPA文件到App Store Connect +# ============================================== +echo -e "\n${YELLOW}🚀 开始上传IPA文件...${NC}" +echo -e " 文件路径:$IPA_PATH" + +xcrun altool --upload-app \ + --type "$APP_TYPE" \ + --file "$IPA_PATH" \ + --apiKey "$API_KEY" \ + --apiIssuer "$API_ISSUER" + +# 上传成功提示 +if [ $? -eq 0 ]; then + echo -e "\n${GREEN}🎉 上传成功!可在App Store Connect中查看构建版本${NC}" + echo -e " 提示:构建版本处理需要几分钟,请耐心等待" +else + echo -e "\n${RED}❌ 上传失败,请根据错误信息修复后重试${NC}" + exit 1 +fi diff --git a/src/api/request.js b/src/api/request.js index 9081ebc3..e9a30160 100644 --- a/src/api/request.js +++ b/src/api/request.js @@ -35,7 +35,7 @@ export const get_base_url = (url = '') => { } // #endif // #ifdef APP-PLUS - return 'https://aitstest.jlbank.com.cn:7002' || ENV.VITE_APP_BASE_API_Url + return ENV.VITE_APP_BASE_API_Url // #endif } else { // 其他环境,包括生产环境,sit环境,uat环境 diff --git a/src/components/points-and-badge/badge.vue b/src/components/points-and-badge/badge.vue index 0754586f..af0e637e 100644 --- a/src/components/points-and-badge/badge.vue +++ b/src/components/points-and-badge/badge.vue @@ -1,17 +1,304 @@ - + diff --git a/src/components/points-and-badge/check-in.vue b/src/components/points-and-badge/check-in.vue index 486b2e06..ec8fcadc 100644 --- a/src/components/points-and-badge/check-in.vue +++ b/src/components/points-and-badge/check-in.vue @@ -95,7 +95,7 @@ // 注意:如果天数从1开始(不是0),需要减1再计算 return Math.floor((currentDay - 1) / 7); }); - const emits = defineEmits(['checkInFun']) + const emits = defineEmits(['checkInFun']); // 切换显示状态 const switchStatus = () => { expand.value = !expand.value; @@ -109,14 +109,24 @@ const checkIn = () => { if (checkInLoading.value) return; checkInLoading.value = true; - addPointsByCheckIn({days:6}) + addPointsByCheckIn({ days: continuousDay.value }) .then((res) => { console.log('签到结果', res); checkInLoading.value = false; isSigned.value = true; continuousDay.value = continuousDay.value + 1; - common.msg('签到成功,请明日继续!') - emits('checkInFun', true) + // common.msg('签到成功,请明日继续!') + emits( + 'checkInFun', + true, + [{ changePoints: 5 }], + [ + { + pointsBadgeImg: '/traoss/tras3/show/S3F0250181220722025110713501700000661177', + pointsBadgeName: '黄金徽章' + } + ] + ); }) .catch((err) => { checkInLoading.value = false; @@ -195,11 +205,11 @@ return groupedList; } - - const open = (checkInToday,days) => { - isSigned.value = checkInToday==='Y'?true:false// 今日签到状态 - // isSigned.value = false// 今日签到状态 - continuousDay.value = days // 连续签到 + + const open = (checkInToday, days) => { + isSigned.value = checkInToday === 'Y' ? true : false; // 今日签到状态 + isSigned.value = false; // 今日签到状态 + continuousDay.value = days; // 连续签到 // 示例:X=10时,以"10天前"为第1天,生成35天列表 try { const X = continuousDay.value - (isSigned.value ? 1 : 0); @@ -207,18 +217,6 @@ console.log(`以${continuousDay.value}天`); console.log(`以${X}天前为第1天的35天分组日期:`); dateGroups.value = generateGroupedDateList(X); - - // dateGroups.value.forEach((group) => { - // console.log(`\n第${group.groupIndex + 1}组:`); - // console.log( - // group.days.map((day) => ({ - // 日期: day.date, - // 天数序号: day.index, // 显示当前是第几天 - // text: day.text, - // 类型: day.type - // })) - // ); - // }); } catch (err) { console.error(err.message); } diff --git a/src/components/points-and-badge/points.vue b/src/components/points-and-badge/points.vue index 02409e35..0b4aaadd 100644 --- a/src/components/points-and-badge/points.vue +++ b/src/components/points-and-badge/points.vue @@ -1,8 +1,171 @@ - - \ No newline at end of file + diff --git a/src/pages/me/index.vue b/src/pages/me/index.vue index 195bc114..4d507197 100644 --- a/src/pages/me/index.vue +++ b/src/pages/me/index.vue @@ -48,8 +48,8 @@ 工号:{{ user_info.loginName }} - - + + @@ -64,7 +64,7 @@ > - + 徽章墙 @@ -97,7 +97,7 @@ - + AI陪练记录 @@ -159,6 +159,8 @@ @confirm="avatarOnConfirm" > + + @@ -179,6 +181,8 @@ import useUpdateAvatar from '@/composables/useUpdateAvatar'; import { queryCurrentStatus, queryCheckIn } from '@/api/pointsAndRank.js'; import checkIn from '@/components/points-and-badge/check-in'; + import badge from '@/components/points-and-badge/badge'; + import points from '@/components/points-and-badge/points'; const { avatarCropperUrl, click_update_avatar, avatarCropperStatus, avatarOnCancel, avatarOnConfirm } = useUpdateAvatar({ success: (userData) => { user_info.imageAddr = userData.imageAddr; @@ -220,8 +224,10 @@ const socketStore = useSocketStore(); const badgeNumRef = ref(null); const checkInRef = ref(null); + const badgeRef = ref(null); + const pointsRef = ref(null); const currentPointsRef = ref(null); - + const user_info = reactive({ userName: '', userId: '', @@ -231,19 +237,28 @@ checkInDays: 0 // 连续签到天数 }); const goTest = () => { - console.log('goTest'); - // common.navigateTo('/pages/test/index'); + common.navigateTo('/pages/test/index'); + }; + const test = () => { + badgeRef.value.open(); }; // 签到打开 const checkInClick = () => { checkInRef.value.open(user_info.checkInToday, user_info.checkInDays); }; // 签到成功回调 - const checkInFun = (status) => { - if(status) { - getCheckInInfo() + const checkInFun = (status, points = [], pointsBadges = []) => { + if (status) { + getCheckInInfo(); } + pointsRef.value.open(points); + // badgeRef.value.open(points); }; + + // 积分确认 + const pointsConfirm = () => { + + } const click_loginout = () => { common.show('确定退出登录?').then(async (res) => { if (!res) return; diff --git a/src/static/images/pointsAndRank/like.png b/src/static/images/pointsAndRank/like.png new file mode 100644 index 0000000000000000000000000000000000000000..3bbca0aebef8ff28e41dc435af53a18dba738ffe GIT binary patch literal 85216 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 IM6N<$g6u@4v;Y7A literal 0 HcmV?d00001