zcw-shared 1.37.0 → 1.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +8 -0
  2. package/dist/functions/android/modifyGradle.d.ts +1 -0
  3. package/dist/functions/android/modifyGradle.js +45 -0
  4. package/dist/functions/android/modifyGradle.js.map +1 -1
  5. package/dist/functions/auth/parseJwtPayload.d.ts +7 -0
  6. package/dist/functions/auth/parseJwtPayload.js +33 -0
  7. package/dist/functions/auth/parseJwtPayload.js.map +1 -0
  8. package/dist/functions/browser/isWeChat.d.ts +5 -0
  9. package/dist/functions/browser/isWeChat.js +5 -0
  10. package/dist/functions/browser/isWeChat.js.map +1 -0
  11. package/dist/functions/ios/integrateNativePlugin.d.ts +31 -0
  12. package/dist/functions/ios/integrateNativePlugin.js +597 -0
  13. package/dist/functions/ios/integrateNativePlugin.js.map +1 -0
  14. package/dist/functions/ios/integrateQQShare.d.ts +14 -0
  15. package/dist/functions/ios/integrateQQShare.js +132 -0
  16. package/dist/functions/ios/integrateQQShare.js.map +1 -0
  17. package/dist/functions/ios/integrateSinaShare.d.ts +16 -0
  18. package/dist/functions/ios/integrateSinaShare.js +108 -0
  19. package/dist/functions/ios/integrateSinaShare.js.map +1 -0
  20. package/dist/functions/ios/integrateThirdPartyModule.d.ts +62 -0
  21. package/dist/functions/ios/integrateThirdPartyModule.js +874 -0
  22. package/dist/functions/ios/integrateThirdPartyModule.js.map +1 -0
  23. package/dist/functions/ios/integrateWechatOauth.d.ts +14 -0
  24. package/dist/functions/ios/integrateWechatOauth.js +107 -0
  25. package/dist/functions/ios/integrateWechatOauth.js.map +1 -0
  26. package/dist/functions/ios/integrateWechatShare.d.ts +14 -0
  27. package/dist/functions/ios/integrateWechatShare.js +101 -0
  28. package/dist/functions/ios/integrateWechatShare.js.map +1 -0
  29. package/dist/functions/uniapp/app-plus/buildAndroidApp.js +128 -35
  30. package/dist/functions/uniapp/app-plus/buildAndroidApp.js.map +1 -1
  31. package/dist/functions/uniapp/app-plus/buildIOSApp.d.ts +27 -0
  32. package/dist/functions/uniapp/app-plus/buildIOSApp.js +849 -0
  33. package/dist/functions/uniapp/app-plus/buildIOSApp.js.map +1 -0
  34. package/dist/functions/uniapp/parseManifest.d.ts +2 -0
  35. package/dist/functions/uniapp/parseManifest.js +3 -1
  36. package/dist/functions/uniapp/parseManifest.js.map +1 -1
  37. package/dist/vue-hooks/browser/useWechatEnv.d.ts +10 -0
  38. package/dist/vue-hooks/browser/useWechatEnv.js +23 -0
  39. package/dist/vue-hooks/browser/useWechatEnv.js.map +1 -0
  40. package/dist/vue-hooks/browser/useWechatJSSDK.d.ts +47 -0
  41. package/dist/vue-hooks/browser/useWechatJSSDK.js +174 -0
  42. package/dist/vue-hooks/browser/useWechatJSSDK.js.map +1 -0
  43. package/dist/vue-hooks/state/useGlobalSettingsManager.d.ts +2 -6
  44. package/dist/vue-hooks/state/useGlobalSettingsManager.js +20 -19
  45. package/dist/vue-hooks/state/useGlobalSettingsManager.js.map +1 -1
  46. package/dist/vue-hooks/state/useSystemSettingsManager.d.ts +2 -6
  47. package/dist/vue-hooks/state/useSystemSettingsManager.js +16 -15
  48. package/dist/vue-hooks/state/useSystemSettingsManager.js.map +1 -1
  49. package/dist/vue-hooks/state/useTokenManager.d.ts +2 -6
  50. package/dist/vue-hooks/state/useTokenManager.js +16 -15
  51. package/dist/vue-hooks/state/useTokenManager.js.map +1 -1
  52. package/dist/vue-hooks/state/useUserManager.d.ts +2 -6
  53. package/dist/vue-hooks/state/useUserManager.js +14 -13
  54. package/dist/vue-hooks/state/useUserManager.js.map +1 -1
  55. package/package.json +14 -1
  56. package/references/wechat.d.ts +8 -0
  57. package/types/ios-build.d.ts +47 -0
  58. package/types/uniapp-android-build.d.ts +10 -0
  59. package/types/uniapp-ios-build.d.ts +131 -0
@@ -0,0 +1,849 @@
1
+ import { parseManifest } from '../parseManifest';
2
+ import { build } from '../build';
3
+ import { modifyManifest } from '../../android/modifyManifest';
4
+ import { integrateWechatShareIOS } from '../../ios/integrateWechatShare';
5
+ import { integrateWechatOauthIOS } from '../../ios/integrateWechatOauth';
6
+ import { integrateQQShareIOS } from '../../ios/integrateQQShare';
7
+ import { integrateSinaShareIOS } from '../../ios/integrateSinaShare';
8
+ import { integrateNativePluginIOS } from '../../ios/integrateNativePlugin';
9
+ function modifyInfoPlistKeyValue(xmlDoc, keyName, value, valueType = 'string') {
10
+ const dictElement = xmlDoc.getElementsByTagName('dict')[0];
11
+ if (!dictElement)
12
+ return false;
13
+ const childNodes = Array.from(dictElement.childNodes || []).filter((node) => node.nodeType === 1);
14
+ let found = false;
15
+ for (let i = 0; i < childNodes.length; i++) {
16
+ const node = childNodes[i];
17
+ if (node.nodeName === 'key' && node.textContent === keyName) {
18
+ if (i + 1 < childNodes.length) {
19
+ const valueNode = childNodes[i + 1];
20
+ if (valueType === 'string' && valueNode.nodeName === 'string') {
21
+ valueNode.textContent = value;
22
+ found = true;
23
+ }
24
+ else if (valueType === 'true' && (valueNode.nodeName === 'true' || valueNode.nodeName === 'false')) {
25
+ const trueElement = xmlDoc.createElement('true');
26
+ const parentNode = valueNode.parentNode;
27
+ if (parentNode && 'replaceChild' in parentNode) {
28
+ parentNode.replaceChild(trueElement, valueNode);
29
+ }
30
+ found = true;
31
+ }
32
+ }
33
+ break;
34
+ }
35
+ }
36
+ if (!found) {
37
+ const keyElement = xmlDoc.createElement('key');
38
+ keyElement.textContent = keyName;
39
+ let valueElement;
40
+ if (valueType === 'string') {
41
+ valueElement = xmlDoc.createElement('string');
42
+ valueElement.textContent = value;
43
+ }
44
+ else {
45
+ valueElement = xmlDoc.createElement('true');
46
+ }
47
+ dictElement.appendChild(keyElement);
48
+ dictElement.appendChild(valueElement);
49
+ found = true;
50
+ }
51
+ return found;
52
+ }
53
+ function safelyModifyProjectPbxproj(projectPbxprojPath, options, deps) {
54
+ try {
55
+ if (!deps.existsSync(projectPbxprojPath)) {
56
+ return { success: false, error: `project.pbxproj 文件不存在: ${projectPbxprojPath}` };
57
+ }
58
+ let content = deps.readFileSync(projectPbxprojPath, 'utf8');
59
+ let modified = false;
60
+ if (options.bundleId) {
61
+ const bundleIdRegex = /PRODUCT_BUNDLE_IDENTIFIER\s*=\s*[^;]+;/g;
62
+ if (bundleIdRegex.test(content)) {
63
+ content = content.replace(bundleIdRegex, `PRODUCT_BUNDLE_IDENTIFIER = ${options.bundleId};`);
64
+ modified = true;
65
+ }
66
+ }
67
+ if (options.version) {
68
+ const marketingVersionRegex = /MARKETING_VERSION\s*=\s*[^;]+;/g;
69
+ if (marketingVersionRegex.test(content)) {
70
+ content = content.replace(marketingVersionRegex, `MARKETING_VERSION = ${options.version};`);
71
+ modified = true;
72
+ }
73
+ }
74
+ if (options.buildNumber) {
75
+ const currentProjectVersionRegex = /CURRENT_PROJECT_VERSION\s*=\s*[^;]+;/g;
76
+ if (currentProjectVersionRegex.test(content)) {
77
+ content = content.replace(currentProjectVersionRegex, `CURRENT_PROJECT_VERSION = ${options.buildNumber};`);
78
+ modified = true;
79
+ }
80
+ }
81
+ if (options.teamId) {
82
+ const devTeamRegex = /DEVELOPMENT_TEAM\s*=\s*[^;]+;/g;
83
+ if (devTeamRegex.test(content)) {
84
+ content = content.replace(devTeamRegex, `DEVELOPMENT_TEAM = ${options.teamId};`);
85
+ modified = true;
86
+ }
87
+ const devTeamSdkRegex = /"DEVELOPMENT_TEAM\[sdk=iphoneos\*\]"\s*=\s*[^;]+;/g;
88
+ if (devTeamSdkRegex.test(content)) {
89
+ content = content.replace(devTeamSdkRegex, `"DEVELOPMENT_TEAM[sdk=iphoneos*]" = ${options.teamId};`);
90
+ modified = true;
91
+ }
92
+ }
93
+ if (options.codeSignIdentity) {
94
+ const identity = options.codeSignIdentity;
95
+ const codeSignIdentityRegex = /CODE_SIGN_IDENTITY\s*=\s*"[^"]*";/g;
96
+ if (codeSignIdentityRegex.test(content)) {
97
+ content = content.replace(codeSignIdentityRegex, `CODE_SIGN_IDENTITY = "${identity}";`);
98
+ modified = true;
99
+ }
100
+ const codeSignIdentitySdkRegex = /"CODE_SIGN_IDENTITY\[sdk=iphoneos\*\]"\s*=\s*"[^"]*";/g;
101
+ if (codeSignIdentitySdkRegex.test(content)) {
102
+ content = content.replace(codeSignIdentitySdkRegex, `"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "${identity}";`);
103
+ modified = true;
104
+ }
105
+ }
106
+ if (options.clearProvisioningProfile !== false) {
107
+ const provProfileRegex = /PROVISIONING_PROFILE\s*=\s*"[^"]*";/g;
108
+ if (provProfileRegex.test(content)) {
109
+ content = content.replace(provProfileRegex, `PROVISIONING_PROFILE = "";`);
110
+ modified = true;
111
+ }
112
+ const provProfileSpecifierRegex = /PROVISIONING_PROFILE_SPECIFIER\s*=\s*"[^"]*";/g;
113
+ if (provProfileSpecifierRegex.test(content)) {
114
+ content = content.replace(provProfileSpecifierRegex, `PROVISIONING_PROFILE_SPECIFIER = "";`);
115
+ modified = true;
116
+ }
117
+ const provProfileSpecifierSdkRegex = /"PROVISIONING_PROFILE_SPECIFIER\[sdk=iphoneos\*\]"\s*=\s*"[^"]*";/g;
118
+ if (provProfileSpecifierSdkRegex.test(content)) {
119
+ content = content.replace(provProfileSpecifierSdkRegex, `"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "";`);
120
+ modified = true;
121
+ }
122
+ }
123
+ if (modified) {
124
+ deps.writeFileSync(projectPbxprojPath, content, 'utf8');
125
+ }
126
+ return { success: true };
127
+ }
128
+ catch (error) {
129
+ return {
130
+ success: false,
131
+ error: `修改 project.pbxproj 失败: ${error instanceof Error ? error.message : String(error)}`
132
+ };
133
+ }
134
+ }
135
+ export async function buildIOSApp(options, deps) {
136
+ const logs = [];
137
+ if (!options.uniappProjectPath) {
138
+ return {
139
+ success: false,
140
+ error: 'uniappProjectPath 是必需的',
141
+ logs
142
+ };
143
+ }
144
+ if (!options.projectPath) {
145
+ return {
146
+ success: false,
147
+ error: 'projectPath 是必需的',
148
+ logs
149
+ };
150
+ }
151
+ try {
152
+ logs.push('步骤 1: 解析 manifest.json 配置');
153
+ const parseResult = parseManifest(options.uniappProjectPath, {
154
+ existsSync: deps.existsSync,
155
+ readFileSync: deps.readFileSync,
156
+ join: deps.join,
157
+ parse: deps.parse
158
+ });
159
+ if (!parseResult.success) {
160
+ return {
161
+ success: false,
162
+ error: parseResult.error,
163
+ logs
164
+ };
165
+ }
166
+ const manifest = parseResult.manifest;
167
+ const version = manifest.versionName || '1.0.0';
168
+ const buildNumber = manifest.versionCode || '1';
169
+ const projectFiles = deps.readdirSync(options.projectPath).filter(file => file.endsWith('.xcodeproj'));
170
+ if (projectFiles.length === 0) {
171
+ return {
172
+ success: false,
173
+ error: `在 ${options.projectPath} 中未找到 Xcode 项目文件(.xcodeproj)`,
174
+ logs
175
+ };
176
+ }
177
+ const projectFile = projectFiles[0];
178
+ const projectName = projectFile.replace(/\.xcodeproj$/, '');
179
+ logs.push(`找到 Xcode 项目: ${projectFile}`);
180
+ logs.push('步骤 1: 同步 project.pbxproj 版本配置');
181
+ const projectPbxprojPath = deps.join(options.projectPath, projectFile, 'project.pbxproj');
182
+ const pbxprojResult = safelyModifyProjectPbxproj(projectPbxprojPath, {
183
+ bundleId: options.bundleId,
184
+ version,
185
+ buildNumber,
186
+ teamId: options.signing?.teamId,
187
+ codeSignIdentity: 'Apple Development'
188
+ }, {
189
+ existsSync: deps.existsSync,
190
+ readFileSync: deps.readFileSync,
191
+ writeFileSync: deps.writeFileSync
192
+ });
193
+ if (pbxprojResult.success) {
194
+ logs.push('project.pbxproj 版本配置同步完成');
195
+ }
196
+ else {
197
+ logs.push(`project.pbxproj 版本配置同步失败: ${pbxprojResult.error}`);
198
+ }
199
+ logs.push('步骤 2: 修改 Info.plist 配置');
200
+ const infoPlistPath = deps.join(options.projectPath, projectName, `${projectName}-Info.plist`);
201
+ if (deps.existsSync(infoPlistPath)) {
202
+ try {
203
+ const xmlContent = deps.readFileSync(infoPlistPath, 'utf8');
204
+ const parser = new deps.xmlParser();
205
+ const xmlDoc = parser.parseFromString(xmlContent, 'text/xml');
206
+ if (options.appkey) {
207
+ modifyInfoPlistKeyValue(xmlDoc, 'dcloud_appkey', options.appkey, 'string');
208
+ }
209
+ if (options.bundleId) {
210
+ modifyInfoPlistKeyValue(xmlDoc, 'CFBundleIdentifier', options.bundleId, 'string');
211
+ }
212
+ if (version) {
213
+ modifyInfoPlistKeyValue(xmlDoc, 'CFBundleShortVersionString', version, 'string');
214
+ }
215
+ if (buildNumber) {
216
+ modifyInfoPlistKeyValue(xmlDoc, 'CFBundleVersion', buildNumber, 'string');
217
+ }
218
+ if (manifest.name) {
219
+ modifyInfoPlistKeyValue(xmlDoc, 'CFBundleDisplayName', manifest.name, 'string');
220
+ }
221
+ if (options.enableIDFA) {
222
+ const dictElement = xmlDoc.getElementsByTagName('dict')[0];
223
+ if (dictElement) {
224
+ const keyElements = xmlDoc.getElementsByTagName('key');
225
+ let found = false;
226
+ for (let i = 0; i < keyElements.length; i++) {
227
+ const keyElement = keyElements[i];
228
+ if (keyElement.textContent === 'NSUserTrackingUsageDescription') {
229
+ found = true;
230
+ break;
231
+ }
232
+ }
233
+ if (!found) {
234
+ const keyElement = xmlDoc.createElement('key');
235
+ keyElement.textContent = 'NSUserTrackingUsageDescription';
236
+ const stringElement = xmlDoc.createElement('string');
237
+ stringElement.textContent = '我们需要您的同意以提供更好的广告体验';
238
+ dictElement.appendChild(keyElement);
239
+ dictElement.appendChild(stringElement);
240
+ }
241
+ }
242
+ }
243
+ if (options.buildCustomBase) {
244
+ modifyInfoPlistKeyValue(xmlDoc, 'UIFileSharingEnabled', '', 'true');
245
+ }
246
+ const serializer = new deps.xmlSerializer();
247
+ const newXmlContent = serializer.serializeToString(xmlDoc);
248
+ deps.writeFileSync(infoPlistPath, newXmlContent, 'utf8');
249
+ logs.push('Info.plist 配置完成');
250
+ if (options.enableIDFA) {
251
+ logs.push('IDFA 配置完成');
252
+ }
253
+ if (options.buildCustomBase) {
254
+ logs.push('Application supports iTunes file sharing 配置完成');
255
+ }
256
+ }
257
+ catch (error) {
258
+ logs.push(`配置 Info.plist 失败: ${error instanceof Error ? error.message : String(error)}`);
259
+ }
260
+ }
261
+ if (options.appIconPath) {
262
+ logs.push('步骤 2: 配置 App Icons Source');
263
+ logs.push('App Icons Source 配置(待实现)');
264
+ }
265
+ if (options.launchScreenPath) {
266
+ logs.push('步骤 3: 配置 LaunchScreen');
267
+ logs.push('LaunchScreen 配置(待实现)');
268
+ }
269
+ if (options.buildCustomBase) {
270
+ logs.push('步骤 4: 配置自定义基座(control.xml)');
271
+ const controlXmlPath = deps.join(options.projectPath, projectName, 'control.xml');
272
+ if (deps.existsSync(controlXmlPath)) {
273
+ const controlModifications = [
274
+ {
275
+ xpath: "//HBuilder",
276
+ action: 'setAttribute',
277
+ attributeName: 'debug',
278
+ value: 'true'
279
+ },
280
+ {
281
+ xpath: "//HBuilder",
282
+ action: 'setAttribute',
283
+ attributeName: 'syncDebug',
284
+ value: 'true'
285
+ }
286
+ ];
287
+ const controlResult = await modifyManifest(controlXmlPath, controlModifications, {
288
+ existsSync: deps.existsSync,
289
+ readFileSync: deps.readFileSync,
290
+ writeFileSync: deps.writeFileSync,
291
+ xmlParser: deps.xmlParser,
292
+ xmlSerializer: deps.xmlSerializer,
293
+ xpath: deps.xpath
294
+ });
295
+ if (controlResult.success) {
296
+ logs.push('control.xml 自定义基座配置完成:debug="true" syncDebug="true"');
297
+ }
298
+ else {
299
+ logs.push(`配置 control.xml 失败: ${controlResult.error}`);
300
+ }
301
+ }
302
+ }
303
+ logs.push('步骤 8: 编译 UniApp 项目并复制到 apps 目录');
304
+ let sourcePath;
305
+ if (options.uniappBuildOutputPath) {
306
+ logs.push('使用提供的 UniApp 编译结果路径');
307
+ sourcePath = options.uniappBuildOutputPath;
308
+ if (!deps.existsSync(sourcePath)) {
309
+ return {
310
+ success: false,
311
+ error: `提供的编译结果路径不存在: ${sourcePath}`,
312
+ logs
313
+ };
314
+ }
315
+ logs.push(`使用编译结果路径: ${sourcePath}`);
316
+ }
317
+ else {
318
+ logs.push('构建 UniApp 项目');
319
+ const buildDeps = {
320
+ exec: deps.exec,
321
+ join: deps.join,
322
+ existsSync: deps.existsSync,
323
+ setTimeout: deps.setTimeout
324
+ };
325
+ const uniBuildResult = await build(options.uniappProjectPath, 'app-plus', buildDeps);
326
+ if (!uniBuildResult.success) {
327
+ return {
328
+ success: false,
329
+ error: `构建失败: ${uniBuildResult.error}`,
330
+ logs: [...logs, ...uniBuildResult.logs]
331
+ };
332
+ }
333
+ logs.push(...uniBuildResult.logs);
334
+ sourcePath = deps.join(options.uniappProjectPath, 'dist', 'build', 'app');
335
+ }
336
+ const targetPath = deps.join(options.projectPath, projectName, 'Pandora', 'apps', manifest.appid, 'www');
337
+ try {
338
+ const targetDir = deps.dirname(targetPath);
339
+ if (!deps.existsSync(targetDir)) {
340
+ deps.mkdirSync(targetDir, { recursive: true });
341
+ }
342
+ await deps.cp(sourcePath, targetPath, { recursive: true, force: true });
343
+ logs.push('应用资源复制完成');
344
+ }
345
+ catch (error) {
346
+ return {
347
+ success: false,
348
+ error: `复制应用资源失败: ${error instanceof Error ? error.message : String(error)}`,
349
+ logs
350
+ };
351
+ }
352
+ const controlXmlPath = deps.join(options.projectPath, projectName, 'control.xml');
353
+ if (deps.existsSync(controlXmlPath)) {
354
+ const controlModifications = [
355
+ {
356
+ xpath: "//apps/app",
357
+ action: 'removeElement'
358
+ },
359
+ {
360
+ xpath: "//apps",
361
+ action: 'addElement',
362
+ elementName: 'app',
363
+ attributes: {
364
+ appid: manifest.appid,
365
+ appver: '',
366
+ ...(options.appkey ? { appkey: options.appkey } : {})
367
+ }
368
+ }
369
+ ];
370
+ const controlResult = await modifyManifest(controlXmlPath, controlModifications, {
371
+ existsSync: deps.existsSync,
372
+ readFileSync: deps.readFileSync,
373
+ writeFileSync: deps.writeFileSync,
374
+ xmlParser: deps.xmlParser,
375
+ xmlSerializer: deps.xmlSerializer,
376
+ xpath: deps.xpath
377
+ });
378
+ if (controlResult.success) {
379
+ logs.push(`control.xml appid 配置完成,appid: ${manifest.appid}`);
380
+ if (options.appkey) {
381
+ logs.push(`设置 appkey: ${options.appkey}`);
382
+ }
383
+ }
384
+ else {
385
+ logs.push(`配置 control.xml appid 失败: ${controlResult.error}`);
386
+ }
387
+ }
388
+ const bundleId = options.bundleId || 'io.dcloud.HBuilder';
389
+ if (options.wechatShare && bundleId) {
390
+ logs.push('集成微信分享模块');
391
+ const wechatShareResult = await integrateWechatShareIOS(options.projectPath, projectName, bundleId, {
392
+ appId: options.wechatShare.appId,
393
+ universalLinks: options.wechatShare.universalLinks,
394
+ liblibSharePath: options.wechatShare.liblibSharePath,
395
+ libweixinSharePath: options.wechatShare.libweixinSharePath,
396
+ libWeChatSDKPath: options.wechatShare.libWeChatSDKPath
397
+ }, {
398
+ existsSync: deps.existsSync,
399
+ readFileSync: deps.readFileSync,
400
+ writeFileSync: deps.writeFileSync,
401
+ copyFileSync: deps.copyFileSync,
402
+ statSync: deps.statSync,
403
+ mkdirSync: deps.mkdirSync,
404
+ readdirSync: deps.readdirSync,
405
+ cp: deps.cp,
406
+ join: deps.join,
407
+ dirname: deps.dirname,
408
+ basename: deps.basename,
409
+ xmlParser: deps.xmlParser,
410
+ xmlSerializer: deps.xmlSerializer,
411
+ xpath: deps.xpath
412
+ });
413
+ if (wechatShareResult.success) {
414
+ logs.push('微信分享模块集成完成');
415
+ logs.push(...wechatShareResult.logs);
416
+ }
417
+ else {
418
+ logs.push(`微信分享模块集成失败: ${wechatShareResult.error}`);
419
+ logs.push(...wechatShareResult.logs);
420
+ }
421
+ }
422
+ if (options.wechatOauth && bundleId) {
423
+ logs.push('集成微信登录模块');
424
+ const wechatOauthResult = await integrateWechatOauthIOS(options.projectPath, projectName, bundleId, {
425
+ appId: options.wechatOauth.appId,
426
+ universalLinks: options.wechatOauth.universalLinks,
427
+ liblibOauthPath: options.wechatOauth.liblibOauthPath,
428
+ libWXOauthPath: options.wechatOauth.libWXOauthPath,
429
+ libWeChatSDKPath: options.wechatOauth.libWeChatSDKPath
430
+ }, {
431
+ existsSync: deps.existsSync,
432
+ readFileSync: deps.readFileSync,
433
+ writeFileSync: deps.writeFileSync,
434
+ copyFileSync: deps.copyFileSync,
435
+ statSync: deps.statSync,
436
+ mkdirSync: deps.mkdirSync,
437
+ readdirSync: deps.readdirSync,
438
+ cp: deps.cp,
439
+ join: deps.join,
440
+ dirname: deps.dirname,
441
+ basename: deps.basename,
442
+ xmlParser: deps.xmlParser,
443
+ xmlSerializer: deps.xmlSerializer,
444
+ xpath: deps.xpath
445
+ });
446
+ if (wechatOauthResult.success) {
447
+ logs.push('微信登录模块集成完成');
448
+ logs.push(...wechatOauthResult.logs);
449
+ }
450
+ else {
451
+ logs.push(`微信登录模块集成失败: ${wechatOauthResult.error}`);
452
+ logs.push(...wechatOauthResult.logs);
453
+ }
454
+ }
455
+ if (options.qqShare && bundleId) {
456
+ logs.push('集成QQ分享模块');
457
+ const qqShareResult = await integrateQQShareIOS(options.projectPath, projectName, bundleId, {
458
+ appId: options.qqShare.appId,
459
+ universalLinks: options.qqShare.universalLinks,
460
+ liblibSharePath: options.qqShare.liblibSharePath,
461
+ libQQSharePath: options.qqShare.libQQSharePath,
462
+ tencentOpenAPIPath: options.qqShare.tencentOpenAPIPath
463
+ }, {
464
+ existsSync: deps.existsSync,
465
+ readFileSync: deps.readFileSync,
466
+ writeFileSync: deps.writeFileSync,
467
+ copyFileSync: deps.copyFileSync,
468
+ statSync: deps.statSync,
469
+ mkdirSync: deps.mkdirSync,
470
+ readdirSync: deps.readdirSync,
471
+ cp: deps.cp,
472
+ join: deps.join,
473
+ dirname: deps.dirname,
474
+ basename: deps.basename,
475
+ xmlParser: deps.xmlParser,
476
+ xmlSerializer: deps.xmlSerializer,
477
+ xpath: deps.xpath
478
+ });
479
+ if (qqShareResult.success) {
480
+ logs.push('QQ分享模块集成完成');
481
+ logs.push(...qqShareResult.logs);
482
+ }
483
+ else {
484
+ logs.push(`QQ分享模块集成失败: ${qqShareResult.error}`);
485
+ logs.push(...qqShareResult.logs);
486
+ }
487
+ }
488
+ if (options.sinaShare && bundleId) {
489
+ logs.push('集成新浪微博分享模块');
490
+ const sinaShareResult = await integrateSinaShareIOS(options.projectPath, projectName, bundleId, {
491
+ appKey: options.sinaShare.appKey,
492
+ appSecret: options.sinaShare.appSecret,
493
+ redirectUri: options.sinaShare.redirectUri,
494
+ liblibSharePath: options.sinaShare.liblibSharePath,
495
+ libSinaSharePath: options.sinaShare.libSinaSharePath,
496
+ libWeiboSDKPath: options.sinaShare.libWeiboSDKPath,
497
+ weiboSDKBundlePath: options.sinaShare.weiboSDKBundlePath
498
+ }, {
499
+ existsSync: deps.existsSync,
500
+ readFileSync: deps.readFileSync,
501
+ writeFileSync: deps.writeFileSync,
502
+ copyFileSync: deps.copyFileSync,
503
+ statSync: deps.statSync,
504
+ mkdirSync: deps.mkdirSync,
505
+ readdirSync: deps.readdirSync,
506
+ cp: deps.cp,
507
+ join: deps.join,
508
+ dirname: deps.dirname,
509
+ basename: deps.basename,
510
+ xmlParser: deps.xmlParser,
511
+ xmlSerializer: deps.xmlSerializer,
512
+ xpath: deps.xpath
513
+ });
514
+ if (sinaShareResult.success) {
515
+ logs.push('新浪微博分享模块集成完成');
516
+ logs.push(...sinaShareResult.logs);
517
+ }
518
+ else {
519
+ logs.push(`新浪微博分享模块集成失败: ${sinaShareResult.error}`);
520
+ logs.push(...sinaShareResult.logs);
521
+ }
522
+ }
523
+ if (options.nativePlugins && options.nativePlugins.length > 0) {
524
+ logs.push('集成 UniApp 原生插件');
525
+ for (const pluginConfig of options.nativePlugins) {
526
+ const pluginResult = await integrateNativePluginIOS(options.projectPath, projectName, pluginConfig.pluginPath, {
527
+ existsSync: deps.existsSync,
528
+ readFileSync: deps.readFileSync,
529
+ writeFileSync: deps.writeFileSync,
530
+ copyFileSync: deps.copyFileSync,
531
+ statSync: deps.statSync,
532
+ mkdirSync: deps.mkdirSync,
533
+ readdirSync: deps.readdirSync,
534
+ cp: deps.cp,
535
+ join: deps.join,
536
+ dirname: deps.dirname,
537
+ basename: deps.basename,
538
+ exec: deps.exec,
539
+ parse: deps.parse,
540
+ xmlParser: deps.xmlParser,
541
+ xmlSerializer: deps.xmlSerializer
542
+ }, pluginConfig.parameters);
543
+ if (pluginResult.success) {
544
+ logs.push(`原生插件集成完成: ${pluginConfig.pluginPath}`);
545
+ logs.push(...pluginResult.logs);
546
+ }
547
+ else {
548
+ logs.push(`原生插件集成失败: ${pluginResult.error}`);
549
+ logs.push(...pluginResult.logs);
550
+ }
551
+ }
552
+ }
553
+ logs.push('步骤 9: 编译 iOS 应用');
554
+ const configuration = options.configuration || 'Release';
555
+ const scheme = options.scheme || projectName;
556
+ logs.push(`提示: 签名配置必须在 Xcode 中手动设置`);
557
+ logs.push(`提示: 请打开项目 ${projectFile},在 Signing & Capabilities 中配置 Team`);
558
+ if (options.signing?.teamId) {
559
+ logs.push(`提示: 开发团队 ID 应该是: ${options.signing.teamId}`);
560
+ }
561
+ const buildCommand = `cd "${options.projectPath}" && xcodebuild -project "${projectFile}" -scheme "${scheme}" -configuration "${configuration}" -destination "generic/platform=iOS" -allowProvisioningUpdates -archivePath "${deps.join(options.outputPath || options.projectPath, 'build', `${projectName}.xcarchive`)}" archive`;
562
+ if (options.clean) {
563
+ logs.push('清理构建目录');
564
+ const cleanCommand = `cd "${options.projectPath}" && xcodebuild -project "${projectFile}" -scheme "${scheme}" -destination "generic/platform=iOS" clean`;
565
+ await new Promise((resolve) => {
566
+ deps.exec(cleanCommand, (error, stdout, stderr) => {
567
+ if (error) {
568
+ logs.push(`清理警告: ${error.message}`);
569
+ }
570
+ if (stdout)
571
+ logs.push(`清理输出: ${stdout}`);
572
+ resolve();
573
+ });
574
+ });
575
+ }
576
+ logs.push(`执行构建命令: ${buildCommand}`);
577
+ const buildResult = await new Promise((resolve) => {
578
+ const child = deps.exec(buildCommand, (error, stdout, stderr) => {
579
+ const allOutput = stdout + (stderr ? '\n' + stderr : '');
580
+ if (error) {
581
+ logs.push(`构建错误: ${error.message}`);
582
+ if (stdout)
583
+ logs.push(`标准输出:\n${stdout}`);
584
+ if (stderr)
585
+ logs.push(`错误输出:\n${stderr}`);
586
+ const errorDetails = allOutput.includes('error:')
587
+ ? allOutput.split('error:').slice(1).join('error:').split('\n').slice(0, 5).join('\n')
588
+ : (stderr || stdout || error.message);
589
+ resolve({
590
+ success: false,
591
+ error: error.message,
592
+ details: errorDetails
593
+ });
594
+ return;
595
+ }
596
+ if (stdout)
597
+ logs.push(`构建输出:\n${stdout}`);
598
+ if (stderr)
599
+ logs.push(`警告信息:\n${stderr}`);
600
+ resolve({ success: true });
601
+ });
602
+ deps.setTimeout(() => {
603
+ child.kill();
604
+ resolve({ success: false, error: '构建超时' });
605
+ }, 600000);
606
+ });
607
+ if (!buildResult.success) {
608
+ const errorMessage = buildResult.details
609
+ ? `编译失败: ${buildResult.error}\n详细信息:\n${buildResult.details}`
610
+ : `编译失败: ${buildResult.error}`;
611
+ return {
612
+ success: false,
613
+ error: errorMessage,
614
+ logs
615
+ };
616
+ }
617
+ const buildBasePath = deps.join(options.outputPath || options.projectPath, 'build');
618
+ const archivePath = deps.join(buildBasePath, `${projectName}.xcarchive`);
619
+ const exportBasePath = deps.join(buildBasePath, 'export');
620
+ if (!deps.existsSync(archivePath)) {
621
+ const errorMessage = `Archive 文件不存在: ${archivePath}`;
622
+ logs.push(errorMessage);
623
+ return {
624
+ success: false,
625
+ error: errorMessage,
626
+ logs
627
+ };
628
+ }
629
+ logs.push(`Archive 文件已找到: ${archivePath}`);
630
+ if (!deps.existsSync(exportBasePath)) {
631
+ deps.mkdirSync(exportBasePath, { recursive: true });
632
+ logs.push(`创建导出目录: ${exportBasePath}`);
633
+ }
634
+ const exportOptionsPlistPath = deps.join(exportBasePath, 'ExportOptions.plist');
635
+ const method = 'development';
636
+ const teamId = options.signing?.teamId;
637
+ const exportOptionsPlistContentLines = [
638
+ '<?xml version="1.0" encoding="UTF-8"?>',
639
+ '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
640
+ '<plist version="1.0">',
641
+ '<dict>',
642
+ ' <key>method</key>',
643
+ ` <string>${method}</string>`,
644
+ ' <key>signingStyle</key>',
645
+ ' <string>automatic</string>'
646
+ ];
647
+ if (teamId) {
648
+ exportOptionsPlistContentLines.push(' <key>teamID</key>');
649
+ exportOptionsPlistContentLines.push(` <string>${teamId}</string>`);
650
+ }
651
+ exportOptionsPlistContentLines.push('</dict>');
652
+ exportOptionsPlistContentLines.push('</plist>');
653
+ const exportOptionsPlistContent = exportOptionsPlistContentLines.join('\n');
654
+ deps.writeFileSync(exportOptionsPlistPath, exportOptionsPlistContent, 'utf8');
655
+ if (!deps.existsSync(exportOptionsPlistPath)) {
656
+ const errorMessage = `ExportOptions.plist 文件创建失败: ${exportOptionsPlistPath}`;
657
+ logs.push(errorMessage);
658
+ return {
659
+ success: false,
660
+ error: errorMessage,
661
+ logs
662
+ };
663
+ }
664
+ logs.push(`ExportOptions.plist 文件已创建: ${exportOptionsPlistPath}`);
665
+ logs.push('开始导出 IPA');
666
+ logs.push(`Archive 路径: ${archivePath}`);
667
+ logs.push(`导出路径: ${exportBasePath}`);
668
+ logs.push(`ExportOptions.plist 路径: ${exportOptionsPlistPath}`);
669
+ logs.push(`ExportOptions.plist 内容:\n${exportOptionsPlistContent}`);
670
+ const exportCommand = `xcodebuild -exportArchive -archivePath "${archivePath}" -exportPath "${exportBasePath}" -exportOptionsPlist "${exportOptionsPlistPath}"`;
671
+ logs.push(`执行导出命令: ${exportCommand}`);
672
+ logs.push('注意:如果导出失败,请检查上面的日志输出,特别是 "导出标准输出" 和 "导出错误/警告输出" 部分');
673
+ const exportResult = await new Promise((resolve) => {
674
+ const child = deps.exec(exportCommand, (error, stdout, stderr) => {
675
+ const allOutput = stdout + (stderr ? '\n' + stderr : '');
676
+ if (stdout) {
677
+ logs.push(`导出标准输出:\n${stdout}`);
678
+ }
679
+ if (stderr) {
680
+ logs.push(`导出错误/警告输出:\n${stderr}`);
681
+ }
682
+ const hasError = allOutput.toLowerCase().includes('error:') ||
683
+ allOutput.toLowerCase().includes('failed') ||
684
+ allOutput.toLowerCase().includes('failure');
685
+ const hasSuccess = allOutput.includes('** EXPORT SUCCEEDED **') ||
686
+ allOutput.toLowerCase().includes('export succeeded') ||
687
+ allOutput.toLowerCase().includes('exportarchive succeeded');
688
+ if (error) {
689
+ logs.push(`导出命令执行错误: ${error.message}`);
690
+ const errorDetails = hasError
691
+ ? allOutput.split(/error:/i).slice(1).join('error:').split('\n').slice(0, 10).join('\n')
692
+ : (stderr || stdout || error.message);
693
+ resolve({
694
+ success: false,
695
+ error: error.message,
696
+ details: errorDetails
697
+ });
698
+ return;
699
+ }
700
+ if (hasError && !hasSuccess) {
701
+ const errorDetails = allOutput.split(/error:/i).slice(1).join('error:').split('\n').slice(0, 10).join('\n');
702
+ resolve({
703
+ success: false,
704
+ error: '导出过程中检测到错误',
705
+ details: errorDetails
706
+ });
707
+ return;
708
+ }
709
+ if (hasSuccess) {
710
+ logs.push('导出命令执行成功(检测到成功标志)');
711
+ resolve({ success: true });
712
+ }
713
+ else if (!hasError && allOutput.trim().length > 0) {
714
+ logs.push('导出命令执行完成(未检测到错误,假设成功)');
715
+ resolve({ success: true });
716
+ }
717
+ else if (!hasError) {
718
+ logs.push('导出命令执行完成(无错误无输出,假设成功)');
719
+ resolve({ success: true });
720
+ }
721
+ else {
722
+ resolve({
723
+ success: false,
724
+ error: '导出结果不明确',
725
+ details: allOutput || '无输出信息'
726
+ });
727
+ }
728
+ });
729
+ deps.setTimeout(() => {
730
+ child.kill();
731
+ resolve({ success: false, error: '导出 IPA 超时' });
732
+ }, 300000);
733
+ });
734
+ if (!exportResult.success) {
735
+ const errorMessage = exportResult.details
736
+ ? `导出 IPA 失败: ${exportResult.error}\n详细信息:\n${exportResult.details}`
737
+ : `导出 IPA 失败: ${exportResult.error}`;
738
+ return {
739
+ success: false,
740
+ error: errorMessage,
741
+ logs
742
+ };
743
+ }
744
+ let ipaPath;
745
+ try {
746
+ if (deps.existsSync(exportBasePath)) {
747
+ const topLevelFiles = deps.readdirSync(exportBasePath);
748
+ logs.push(`导出目录内容: ${topLevelFiles.join(', ')}`);
749
+ }
750
+ else {
751
+ logs.push(`警告: 导出目录不存在: ${exportBasePath}`);
752
+ }
753
+ const findIpaFile = (dir, depth = 0) => {
754
+ if (depth > 3) {
755
+ return undefined;
756
+ }
757
+ if (!deps.existsSync(dir)) {
758
+ return undefined;
759
+ }
760
+ const files = deps.readdirSync(dir);
761
+ logs.push(`搜索目录 (深度 ${depth}): ${dir}, 文件数: ${files.length}`);
762
+ const ipaFile = files.find(f => f.toLowerCase().endsWith('.ipa'));
763
+ if (ipaFile) {
764
+ const foundPath = deps.join(dir, ipaFile);
765
+ logs.push(`找到 IPA 文件: ${foundPath}`);
766
+ return foundPath;
767
+ }
768
+ for (const file of files) {
769
+ const fullPath = deps.join(dir, file);
770
+ try {
771
+ const stat = deps.statSync(fullPath);
772
+ if (stat.isDirectory()) {
773
+ const found = findIpaFile(fullPath, depth + 1);
774
+ if (found) {
775
+ return found;
776
+ }
777
+ }
778
+ }
779
+ catch (err) {
780
+ continue;
781
+ }
782
+ }
783
+ return undefined;
784
+ };
785
+ ipaPath = findIpaFile(exportBasePath);
786
+ }
787
+ catch (error) {
788
+ logs.push(`查找 IPA 文件时出错: ${error instanceof Error ? error.message : String(error)}`);
789
+ }
790
+ if (!ipaPath) {
791
+ const listDirectory = (dir, prefix = '') => {
792
+ const lines = [];
793
+ try {
794
+ if (!deps.existsSync(dir)) {
795
+ return [`${prefix}[目录不存在]`];
796
+ }
797
+ const files = deps.readdirSync(dir);
798
+ for (const file of files) {
799
+ const fullPath = deps.join(dir, file);
800
+ try {
801
+ const stat = deps.statSync(fullPath);
802
+ if (stat.isDirectory()) {
803
+ lines.push(`${prefix}${file}/`);
804
+ lines.push(...listDirectory(fullPath, prefix + ' '));
805
+ }
806
+ else {
807
+ lines.push(`${prefix}${file}`);
808
+ }
809
+ }
810
+ catch {
811
+ lines.push(`${prefix}${file} [无法访问]`);
812
+ }
813
+ }
814
+ }
815
+ catch {
816
+ lines.push(`${prefix}[无法读取目录]`);
817
+ }
818
+ return lines;
819
+ };
820
+ const dirStructure = listDirectory(exportBasePath);
821
+ const errorMessage = `导出成功但未找到 IPA 文件,导出路径: ${exportBasePath}`;
822
+ logs.push(errorMessage);
823
+ logs.push('导出目录结构:');
824
+ logs.push(...dirStructure);
825
+ logs.push('请检查 xcodebuild 导出日志,确认是否有错误');
826
+ return {
827
+ success: false,
828
+ error: errorMessage,
829
+ logs
830
+ };
831
+ }
832
+ logs.push('iOS 离线打包完成');
833
+ logs.push(`IPA 文件已生成: ${ipaPath}`);
834
+ return {
835
+ success: true,
836
+ outputPath: ipaPath,
837
+ logs
838
+ };
839
+ }
840
+ catch (error) {
841
+ const errorMessage = error instanceof Error ? error.message : String(error);
842
+ return {
843
+ success: false,
844
+ error: `打包过程中发生异常: ${errorMessage}`,
845
+ logs
846
+ };
847
+ }
848
+ }
849
+ //# sourceMappingURL=buildIOSApp.js.map