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)