From e10afb180de24c3598285616decda8efd89f31f5 Mon Sep 17 00:00:00 2001 From: shenlei Date: Fri, 28 Aug 2026 16:38:22 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20APP=20=E9=85=8D=E7=BD=AE=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1=20Schema=EF=BC=8C?= =?UTF-8?q?=E5=86=99=E5=85=A5=20Info.plist=20wxworkSchema=20=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 与微信登录 AppID 处理一致:填写则写入 Info.plist 的 wxworkSchema, 未配置则移除该键。前端「关联配置」区新增输入框,打包流程透传该字段。 Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_011wQh7H1Dn3TjQm87TyYgvf --- backend/services/build_service.py | 2 +- backend/services/project_patcher.py | 8 +++++ config.example.json | 1 + frontend/src/views/ConfigView.vue | 7 +++++ tests/test_project_patcher.py | 46 +++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/backend/services/build_service.py b/backend/services/build_service.py index b64acc2..952cadf 100644 --- a/backend/services/build_service.py +++ b/backend/services/build_service.py @@ -722,7 +722,7 @@ async def generate_config(task_id: str, task, build_dir: Path) -> dict: # 关联域名等配置 config_data["ASSOCIATED_DOMAINS"] = app.get("AssDom", "") - for key in ["weixinlogin", "weixinpay", "tencent", "UniversalLink", "AlivcLicenseKey"]: + for key in ["weixinlogin", "weixinpay", "wxworkSchema", "tencent", "UniversalLink", "AlivcLicenseKey"]: if key in app: config_data[key] = app[key] diff --git a/backend/services/project_patcher.py b/backend/services/project_patcher.py index 2948e2d..d7f1684 100644 --- a/backend/services/project_patcher.py +++ b/backend/services/project_patcher.py @@ -35,6 +35,14 @@ def _update_plist(path: Path, config: dict): plist["CFBundleDisplayName"] = config.get("APPID_NAME", "") plist["AlivcLicenseKey"] = config.get("AlivcLicenseKey", "") or "" + + # 企业微信 Schema:与微信登录 AppID 处理方式一致,未配置则移除该键。 + wxwork_schema = (config.get("wxworkSchema", "") or "").strip() + if wxwork_schema: + plist["wxworkSchema"] = wxwork_schema + else: + plist.pop("wxworkSchema", None) + scheme = (config.get("BUNDLE_ID", "") or "").replace(".", "").lower() values = { "weixinlogin": config.get("weixinlogin", ""), diff --git a/config.example.json b/config.example.json index bfd9bb8..4df4711 100644 --- a/config.example.json +++ b/config.example.json @@ -11,6 +11,7 @@ "tencent": "", "weixinlogin": "", "weixinpay": "", + "wxworkSchema": "", "skins": ["default.zip"], "certificates": { "Ad_Hoc": { diff --git a/frontend/src/views/ConfigView.vue b/frontend/src/views/ConfigView.vue index d63cdb0..4976769 100644 --- a/frontend/src/views/ConfigView.vue +++ b/frontend/src/views/ConfigView.vue @@ -488,6 +488,12 @@ +
+
+ + +
+
@@ -883,6 +889,7 @@ const openAppModal = (id = null, app = null) => { UniversalLink: '', weixinlogin: '', weixinpay: '', + wxworkSchema: '', tencent: '', AlivcLicenseKey: '', app_id_prefix_override: '', diff --git a/tests/test_project_patcher.py b/tests/test_project_patcher.py index 75a850f..4145d1c 100644 --- a/tests/test_project_patcher.py +++ b/tests/test_project_patcher.py @@ -42,6 +42,7 @@ def test_apply_project_config_without_branch_autopacking(tmp_path): config = { "VERSION": "2.0.0", "BUILD_VERSION": "2.0.0.1", "APPID": "guid", "API": "https://api.example.com", "weixinpay": "wx-pay", "APPID_NAME": "Test", + "wxworkSchema": "wx1234567890abcdef", "BUNDLE_ID": "com.example.test", "TEAM_ID": "TEAM", "PROVISIONING_NAME": "profile", "ASSOCIATED_DOMAINS": "applinks:example.com", "THEME": str(theme.parent), "BUILD_TYPE": "Ad_Hoc", "CERTIFICATE": "Apple Distribution", @@ -58,3 +59,48 @@ def test_apply_project_config_without_branch_autopacking(tmp_path): assert "iPhone Developer" not in project_content assert (build_dir / "exportOptions.plist").exists() assert (logo / "icon-1024.png").read_bytes() == b"icon" + with (build_dir / "readoor" / "3.0" / "readoor31.plist").open("rb") as f: + assert plistlib.load(f)["wxworkSchema"] == "wx1234567890abcdef" + + +def _make_minimal_project(build_dir): + """构造 apply_project_config 所需的最小工程骨架,返回关键文件路径。""" + project = build_dir / "readoor.xcodeproj" + swift = build_dir / "readoor" / "3.0" / "AppConfig" + entitlements_dir = build_dir / "readoor" / "3.0" + for path in [project, swift, entitlements_dir]: + path.mkdir(parents=True, exist_ok=True) + (project / "project.pbxproj").write_text( + "MARKETING_VERSION = 1.0;\nCURRENT_PROJECT_VERSION = 1;\n" + 'CODE_SIGN_IDENTITY = "iPhone Developer";\n' + '"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";\n', + encoding="utf-8", + ) + (swift / "RDAppConfiguration.swift").write_text( + 'let RD_APP_GUID: String = "old"\nlet RD_API_DOMAIN: String = "old"\n' + 'let RD_WECHAT_PAY_ID: String = "old"\nlet RD_SOURCE_VERSION: String = "old"\n', + encoding="utf-8", + ) + (entitlements_dir / "readoor31.entitlements").write_text( + "applinks:old\n", encoding="utf-8" + ) + return entitlements_dir / "readoor31.plist" + + +def test_wxwork_schema_removed_when_not_configured(tmp_path): + build_dir = tmp_path / "build" + plist_path = _make_minimal_project(build_dir) + with plist_path.open("wb") as f: + plistlib.dump({"CFBundleURLTypes": [], "wxworkSchema": "stale-value"}, f) + + config = { + "VERSION": "2.0.0", "BUILD_VERSION": "2.0.0.1", "APPID": "guid", + "API": "https://api.example.com", "APPID_NAME": "Test", + "ASSOCIATED_DOMAINS": "applinks:example.com", "BUILD_TYPE": "Ad_Hoc", + "CERTIFICATE": "Apple Distribution", + } + + apply_project_config(build_dir, config) + + with plist_path.open("rb") as f: + assert "wxworkSchema" not in plistlib.load(f)