zcw-shared 1.45.0 → 1.46.1
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.
- package/dist/functions/android/integrateUniAppNativePlugin.d.ts +9 -9
- package/dist/functions/android/integrateUniAppNativePlugin.js +148 -104
- package/dist/functions/android/integrateUniAppNativePlugin.js.map +1 -1
- package/dist/functions/ios/integrateNativePlugin.d.ts +20 -16
- package/dist/functions/ios/integrateNativePlugin.js +585 -188
- package/dist/functions/ios/integrateNativePlugin.js.map +1 -1
- package/dist/functions/ios/integrateThirdPartyModule.js +61 -9
- package/dist/functions/ios/integrateThirdPartyModule.js.map +1 -1
- package/dist/functions/ios/safelyModifyProjectPbxproj.js +69 -20
- package/dist/functions/ios/safelyModifyProjectPbxproj.js.map +1 -1
- package/dist/functions/uniapp/app-plus/buildIOSApp.d.ts +3 -1
- package/dist/functions/uniapp/app-plus/buildIOSApp.js +158 -147
- package/dist/functions/uniapp/app-plus/buildIOSApp.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,33 +10,32 @@ import { configureIOSPermissions } from '../../ios/configurePermissions';
|
|
|
10
10
|
import { modifyInfoPlistKeyValue } from '../../ios/modifyInfoPlistKeyValue';
|
|
11
11
|
import { safelyModifyProjectPbxproj } from '../../ios/safelyModifyProjectPbxproj';
|
|
12
12
|
export async function buildIOSApp(options, deps) {
|
|
13
|
-
const logs = [];
|
|
14
13
|
if (!options.uniappProjectPath) {
|
|
15
14
|
return {
|
|
16
15
|
success: false,
|
|
17
16
|
error: 'uniappProjectPath 是必需的',
|
|
18
|
-
logs
|
|
17
|
+
logs: []
|
|
19
18
|
};
|
|
20
19
|
}
|
|
21
20
|
if (!options.projectPath) {
|
|
22
21
|
return {
|
|
23
22
|
success: false,
|
|
24
23
|
error: 'projectPath 是必需的',
|
|
25
|
-
logs
|
|
24
|
+
logs: []
|
|
26
25
|
};
|
|
27
26
|
}
|
|
28
27
|
if (!options.uniAppId) {
|
|
29
28
|
return {
|
|
30
29
|
success: false,
|
|
31
30
|
error: 'uniAppId 是必需的',
|
|
32
|
-
logs
|
|
31
|
+
logs: []
|
|
33
32
|
};
|
|
34
33
|
}
|
|
35
34
|
if (!options.displayName) {
|
|
36
35
|
return {
|
|
37
36
|
success: false,
|
|
38
37
|
error: 'displayName 是必需的',
|
|
39
|
-
logs
|
|
38
|
+
logs: []
|
|
40
39
|
};
|
|
41
40
|
}
|
|
42
41
|
try {
|
|
@@ -47,16 +46,16 @@ export async function buildIOSApp(options, deps) {
|
|
|
47
46
|
return {
|
|
48
47
|
success: false,
|
|
49
48
|
error: `在 ${options.projectPath} 中未找到 Xcode 项目文件(.xcodeproj)`,
|
|
50
|
-
logs
|
|
49
|
+
logs: []
|
|
51
50
|
};
|
|
52
51
|
}
|
|
53
52
|
const projectFile = projectFiles[0];
|
|
54
53
|
const projectName = options.sourceDirectoryName || projectFile.replace(/\.xcodeproj$/, '');
|
|
55
|
-
|
|
54
|
+
deps.log(`找到 Xcode 项目: ${projectFile}`);
|
|
56
55
|
if (options.sourceDirectoryName) {
|
|
57
|
-
|
|
56
|
+
deps.log(`使用指定的源码目录: ${projectName}`);
|
|
58
57
|
}
|
|
59
|
-
|
|
58
|
+
deps.log('步骤 1: 同步 project.pbxproj 版本配置');
|
|
60
59
|
const projectPbxprojPath = deps.join(options.projectPath, projectFile, 'project.pbxproj');
|
|
61
60
|
const pbxprojResult = safelyModifyProjectPbxproj(projectPbxprojPath, {
|
|
62
61
|
bundleId: options.bundleId,
|
|
@@ -70,12 +69,12 @@ export async function buildIOSApp(options, deps) {
|
|
|
70
69
|
writeFileSync: deps.writeFileSync
|
|
71
70
|
});
|
|
72
71
|
if (pbxprojResult.success) {
|
|
73
|
-
|
|
72
|
+
deps.log('project.pbxproj 版本配置同步完成');
|
|
74
73
|
}
|
|
75
74
|
else {
|
|
76
|
-
|
|
75
|
+
deps.log(`project.pbxproj 版本配置同步失败: ${pbxprojResult.error}`);
|
|
77
76
|
}
|
|
78
|
-
|
|
77
|
+
deps.log('步骤 2: 修改 Info.plist 配置');
|
|
79
78
|
const infoPlistPath = deps.join(options.projectPath, projectName, `${projectName}-Info.plist`);
|
|
80
79
|
if (deps.existsSync(infoPlistPath)) {
|
|
81
80
|
try {
|
|
@@ -125,20 +124,20 @@ export async function buildIOSApp(options, deps) {
|
|
|
125
124
|
const serializer = new deps.xmlSerializer();
|
|
126
125
|
const newXmlContent = serializer.serializeToString(xmlDoc);
|
|
127
126
|
deps.writeFileSync(infoPlistPath, newXmlContent, 'utf8');
|
|
128
|
-
|
|
127
|
+
deps.log('Info.plist 配置完成');
|
|
129
128
|
if (options.enableIDFA) {
|
|
130
|
-
|
|
129
|
+
deps.log('IDFA 配置完成');
|
|
131
130
|
}
|
|
132
131
|
if (options.buildCustomBase) {
|
|
133
|
-
|
|
132
|
+
deps.log('Application supports iTunes file sharing 配置完成');
|
|
134
133
|
}
|
|
135
134
|
}
|
|
136
135
|
catch (error) {
|
|
137
|
-
|
|
136
|
+
deps.log(`配置 Info.plist 失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
138
137
|
}
|
|
139
138
|
}
|
|
140
139
|
if (options.permissions && options.permissions.length > 0) {
|
|
141
|
-
|
|
140
|
+
deps.log('步骤 2.1: 配置 iOS 权限');
|
|
142
141
|
const permissionsResult = await configureIOSPermissions(infoPlistPath, options.permissions, undefined, {
|
|
143
142
|
existsSync: deps.existsSync,
|
|
144
143
|
readFileSync: deps.readFileSync,
|
|
@@ -147,16 +146,16 @@ export async function buildIOSApp(options, deps) {
|
|
|
147
146
|
xmlSerializer: deps.xmlSerializer
|
|
148
147
|
});
|
|
149
148
|
if (permissionsResult.success) {
|
|
150
|
-
|
|
151
|
-
logs.
|
|
149
|
+
deps.log('iOS 权限配置完成');
|
|
150
|
+
permissionsResult.logs.forEach(msg => deps.log(msg));
|
|
152
151
|
}
|
|
153
152
|
else {
|
|
154
|
-
|
|
155
|
-
logs.
|
|
153
|
+
deps.log(`iOS 权限配置失败: ${permissionsResult.error}`);
|
|
154
|
+
permissionsResult.logs.forEach(msg => deps.log(msg));
|
|
156
155
|
}
|
|
157
156
|
}
|
|
158
157
|
if (options.displayName) {
|
|
159
|
-
|
|
158
|
+
deps.log('步骤 2.2: 修改本地化字符串文件');
|
|
160
159
|
const projectDir = deps.join(options.projectPath, projectName);
|
|
161
160
|
const lprojDirs = ['en.lproj', 'zh-Hans.lproj', 'zh-Hant.lproj', 'Base.lproj', 'English.lproj'];
|
|
162
161
|
for (const lprojDir of lprojDirs) {
|
|
@@ -172,18 +171,18 @@ export async function buildIOSApp(options, deps) {
|
|
|
172
171
|
content += `\nCFBundleDisplayName="${options.displayName}";\n`;
|
|
173
172
|
}
|
|
174
173
|
deps.writeFileSync(infoPlistStringsPath, content, 'utf8');
|
|
175
|
-
|
|
174
|
+
deps.log(`已更新 ${lprojDir}/InfoPlist.strings`);
|
|
176
175
|
}
|
|
177
176
|
catch (error) {
|
|
178
|
-
|
|
177
|
+
deps.log(`更新 ${lprojDir}/InfoPlist.strings 失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
179
178
|
}
|
|
180
179
|
}
|
|
181
180
|
}
|
|
182
181
|
}
|
|
183
182
|
if (options.appIconPath) {
|
|
184
|
-
|
|
183
|
+
deps.log('步骤 2: 配置 App Icons Source');
|
|
185
184
|
if (!deps.sharp) {
|
|
186
|
-
|
|
185
|
+
deps.log('警告: 未提供 sharp 依赖,跳过图标配置。请安装 sharp 并在 deps 中传入。');
|
|
187
186
|
}
|
|
188
187
|
else {
|
|
189
188
|
const appIconResult = await configureAppIconIOS(options.appIconPath, options.projectPath, projectName, {
|
|
@@ -196,19 +195,19 @@ export async function buildIOSApp(options, deps) {
|
|
|
196
195
|
sharp: deps.sharp
|
|
197
196
|
});
|
|
198
197
|
if (appIconResult.success) {
|
|
199
|
-
|
|
200
|
-
logs.
|
|
198
|
+
deps.log('App Icons Source 配置完成');
|
|
199
|
+
appIconResult.logs.forEach(msg => deps.log(msg));
|
|
201
200
|
}
|
|
202
201
|
else {
|
|
203
|
-
|
|
204
|
-
logs.
|
|
202
|
+
deps.log(`App Icons Source 配置失败: ${appIconResult.error}`);
|
|
203
|
+
appIconResult.logs.forEach(msg => deps.log(msg));
|
|
205
204
|
}
|
|
206
205
|
}
|
|
207
206
|
}
|
|
208
207
|
if (options.launchScreenPath) {
|
|
209
|
-
|
|
208
|
+
deps.log('步骤 3: 配置 LaunchScreen');
|
|
210
209
|
if (!deps.sharp) {
|
|
211
|
-
|
|
210
|
+
deps.log('警告: 未提供 sharp 依赖,跳过启动屏配置。请安装 sharp 并在 deps 中传入。');
|
|
212
211
|
}
|
|
213
212
|
else {
|
|
214
213
|
const launchScreenResult = await configureLaunchScreen(options.launchScreenPath, options.projectPath, projectName, {
|
|
@@ -221,17 +220,17 @@ export async function buildIOSApp(options, deps) {
|
|
|
221
220
|
sharp: deps.sharp
|
|
222
221
|
});
|
|
223
222
|
if (launchScreenResult.success) {
|
|
224
|
-
|
|
225
|
-
logs.
|
|
223
|
+
deps.log('LaunchScreen 配置完成');
|
|
224
|
+
launchScreenResult.logs.forEach(msg => deps.log(msg));
|
|
226
225
|
}
|
|
227
226
|
else {
|
|
228
|
-
|
|
229
|
-
logs.
|
|
227
|
+
deps.log(`LaunchScreen 配置失败: ${launchScreenResult.error}`);
|
|
228
|
+
launchScreenResult.logs.forEach(msg => deps.log(msg));
|
|
230
229
|
}
|
|
231
230
|
}
|
|
232
231
|
}
|
|
233
232
|
if (options.buildCustomBase) {
|
|
234
|
-
|
|
233
|
+
deps.log('步骤 4: 配置自定义基座(control.xml)');
|
|
235
234
|
const controlXmlPath = deps.join(options.projectPath, projectName, 'control.xml');
|
|
236
235
|
if (deps.existsSync(controlXmlPath)) {
|
|
237
236
|
try {
|
|
@@ -254,37 +253,37 @@ export async function buildIOSApp(options, deps) {
|
|
|
254
253
|
const serializer = new deps.xmlSerializer();
|
|
255
254
|
const newXmlContent = serializer.serializeToString(xmlDoc);
|
|
256
255
|
deps.writeFileSync(controlXmlPath, newXmlContent, 'utf8');
|
|
257
|
-
|
|
256
|
+
deps.log('control.xml 自定义基座配置完成:debug="true" syncDebug="true"');
|
|
258
257
|
}
|
|
259
258
|
else {
|
|
260
|
-
|
|
259
|
+
deps.log('control.xml 自定义基座配置已存在,无需修改');
|
|
261
260
|
}
|
|
262
261
|
}
|
|
263
262
|
else {
|
|
264
|
-
|
|
263
|
+
deps.log('警告:未找到 HBuilder 根节点,无法添加自定义基座配置');
|
|
265
264
|
}
|
|
266
265
|
}
|
|
267
266
|
catch (error) {
|
|
268
|
-
|
|
267
|
+
deps.log(`配置 control.xml 失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
269
268
|
}
|
|
270
269
|
}
|
|
271
270
|
}
|
|
272
|
-
|
|
271
|
+
deps.log('步骤 8: 编译 UniApp 项目并复制到 apps 目录');
|
|
273
272
|
let sourcePath;
|
|
274
273
|
if (options.uniappBuildOutputPath) {
|
|
275
|
-
|
|
274
|
+
deps.log('使用提供的 UniApp 编译结果路径');
|
|
276
275
|
sourcePath = options.uniappBuildOutputPath;
|
|
277
276
|
if (!deps.existsSync(sourcePath)) {
|
|
278
277
|
return {
|
|
279
278
|
success: false,
|
|
280
279
|
error: `提供的编译结果路径不存在: ${sourcePath}`,
|
|
281
|
-
logs
|
|
280
|
+
logs: []
|
|
282
281
|
};
|
|
283
282
|
}
|
|
284
|
-
|
|
283
|
+
deps.log(`使用编译结果路径: ${sourcePath}`);
|
|
285
284
|
}
|
|
286
285
|
else {
|
|
287
|
-
|
|
286
|
+
deps.log('构建 UniApp 项目');
|
|
288
287
|
const buildDeps = {
|
|
289
288
|
exec: deps.exec,
|
|
290
289
|
join: deps.join,
|
|
@@ -296,10 +295,10 @@ export async function buildIOSApp(options, deps) {
|
|
|
296
295
|
return {
|
|
297
296
|
success: false,
|
|
298
297
|
error: `构建失败: ${uniBuildResult.error}`,
|
|
299
|
-
logs: [
|
|
298
|
+
logs: []
|
|
300
299
|
};
|
|
301
300
|
}
|
|
302
|
-
logs.
|
|
301
|
+
uniBuildResult.logs.forEach(msg => deps.log(msg));
|
|
303
302
|
sourcePath = deps.join(options.uniappProjectPath, 'dist', 'build', 'app');
|
|
304
303
|
}
|
|
305
304
|
const targetPath = deps.join(options.projectPath, projectName, 'Pandora', 'apps', options.uniAppId, 'www');
|
|
@@ -309,13 +308,13 @@ export async function buildIOSApp(options, deps) {
|
|
|
309
308
|
deps.mkdirSync(targetDir, { recursive: true });
|
|
310
309
|
}
|
|
311
310
|
await deps.cp(sourcePath, targetPath, { recursive: true, force: true });
|
|
312
|
-
|
|
311
|
+
deps.log('应用资源复制完成');
|
|
313
312
|
}
|
|
314
313
|
catch (error) {
|
|
315
314
|
return {
|
|
316
315
|
success: false,
|
|
317
316
|
error: `复制应用资源失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
318
|
-
logs
|
|
317
|
+
logs: []
|
|
319
318
|
};
|
|
320
319
|
}
|
|
321
320
|
const controlXmlPath = deps.join(options.projectPath, projectName, 'control.xml');
|
|
@@ -341,13 +340,13 @@ export async function buildIOSApp(options, deps) {
|
|
|
341
340
|
if (options.appkey && appElement.getAttribute('appkey') !== options.appkey) {
|
|
342
341
|
appElement.setAttribute('appkey', options.appkey);
|
|
343
342
|
hasChanges = true;
|
|
344
|
-
|
|
343
|
+
deps.log(`更新 appkey: ${options.appkey}`);
|
|
345
344
|
}
|
|
346
345
|
if (hasChanges) {
|
|
347
|
-
|
|
346
|
+
deps.log(`更新现有 app 元素,appid: ${options.uniAppId}`);
|
|
348
347
|
}
|
|
349
348
|
else {
|
|
350
|
-
|
|
349
|
+
deps.log(`app 元素已存在且配置正确,appid: ${options.uniAppId}`);
|
|
351
350
|
}
|
|
352
351
|
break;
|
|
353
352
|
}
|
|
@@ -356,41 +355,41 @@ export async function buildIOSApp(options, deps) {
|
|
|
356
355
|
while (existingAppElements.length > 0) {
|
|
357
356
|
appsElement.removeChild(existingAppElements[0]);
|
|
358
357
|
}
|
|
359
|
-
|
|
358
|
+
deps.log('已删除所有现有的 app 元素');
|
|
360
359
|
const newAppElement = xmlDoc.createElement('app');
|
|
361
360
|
newAppElement.setAttribute('appid', options.uniAppId);
|
|
362
361
|
newAppElement.setAttribute('appver', '');
|
|
363
362
|
if (options.appkey) {
|
|
364
363
|
newAppElement.setAttribute('appkey', options.appkey);
|
|
365
|
-
|
|
364
|
+
deps.log(`设置 appkey: ${options.appkey}`);
|
|
366
365
|
}
|
|
367
366
|
appsElement.appendChild(newAppElement);
|
|
368
|
-
|
|
367
|
+
deps.log(`添加新的 app 元素,appid: ${options.uniAppId}`);
|
|
369
368
|
hasChanges = true;
|
|
370
369
|
}
|
|
371
370
|
if (hasChanges || !appExists) {
|
|
372
371
|
const serializer = new deps.xmlSerializer();
|
|
373
372
|
const newXmlContent = serializer.serializeToString(xmlDoc);
|
|
374
373
|
deps.writeFileSync(controlXmlPath, newXmlContent, 'utf8');
|
|
375
|
-
|
|
374
|
+
deps.log(`control.xml appid 配置完成,appid: ${options.uniAppId}`);
|
|
376
375
|
}
|
|
377
376
|
else {
|
|
378
|
-
|
|
377
|
+
deps.log(`control.xml appid 配置已存在,无需修改`);
|
|
379
378
|
}
|
|
380
379
|
}
|
|
381
380
|
else {
|
|
382
|
-
|
|
381
|
+
deps.log('control.xml 中未找到 apps 元素');
|
|
383
382
|
}
|
|
384
383
|
}
|
|
385
384
|
catch (error) {
|
|
386
|
-
|
|
385
|
+
deps.log(`配置 control.xml appid 失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
387
386
|
}
|
|
388
387
|
}
|
|
389
388
|
if (options.appkey && options.sourceDirectoryName) {
|
|
390
389
|
const pluginInfoPlistPath = deps.join(options.projectPath, options.sourceDirectoryName, 'HBuilder-uniPlugin-Info.plist');
|
|
391
390
|
if (deps.existsSync(pluginInfoPlistPath)) {
|
|
392
391
|
try {
|
|
393
|
-
|
|
392
|
+
deps.log('配置插件项目 Info.plist (HBuilder-uniPlugin-Info.plist)');
|
|
394
393
|
const plistContent = deps.readFileSync(pluginInfoPlistPath, 'utf8');
|
|
395
394
|
const parser = new deps.xmlParser();
|
|
396
395
|
const xmlDoc = parser.parseFromString(plistContent, 'text/xml');
|
|
@@ -399,23 +398,23 @@ export async function buildIOSApp(options, deps) {
|
|
|
399
398
|
const serializer = new deps.xmlSerializer();
|
|
400
399
|
const newPlistContent = serializer.serializeToString(xmlDoc);
|
|
401
400
|
deps.writeFileSync(pluginInfoPlistPath, newPlistContent, 'utf8');
|
|
402
|
-
|
|
401
|
+
deps.log(`HBuilder-uniPlugin-Info.plist dcloud_appkey 配置完成: ${options.appkey}`);
|
|
403
402
|
}
|
|
404
403
|
else {
|
|
405
|
-
|
|
404
|
+
deps.log(`HBuilder-uniPlugin-Info.plist dcloud_appkey 配置失败(未找到或无法修改)`);
|
|
406
405
|
}
|
|
407
406
|
}
|
|
408
407
|
catch (error) {
|
|
409
|
-
|
|
408
|
+
deps.log(`配置 HBuilder-uniPlugin-Info.plist 失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
410
409
|
}
|
|
411
410
|
}
|
|
412
411
|
else {
|
|
413
|
-
|
|
412
|
+
deps.log(`HBuilder-uniPlugin-Info.plist 文件不存在: ${pluginInfoPlistPath}`);
|
|
414
413
|
}
|
|
415
414
|
}
|
|
416
415
|
const bundleId = options.bundleId || 'io.dcloud.HBuilder';
|
|
417
416
|
if (options.wechatShare && bundleId) {
|
|
418
|
-
|
|
417
|
+
deps.log('集成微信分享模块');
|
|
419
418
|
const wechatShareResult = await integrateWechatShareIOS(options.projectPath, projectName, bundleId, {
|
|
420
419
|
appId: options.wechatShare.appId,
|
|
421
420
|
universalLinks: options.wechatShare.universalLinks,
|
|
@@ -439,16 +438,16 @@ export async function buildIOSApp(options, deps) {
|
|
|
439
438
|
xpath: deps.xpath
|
|
440
439
|
});
|
|
441
440
|
if (wechatShareResult.success) {
|
|
442
|
-
|
|
443
|
-
logs.
|
|
441
|
+
deps.log('微信分享模块集成完成');
|
|
442
|
+
wechatShareResult.logs.forEach(msg => deps.log(msg));
|
|
444
443
|
}
|
|
445
444
|
else {
|
|
446
|
-
|
|
447
|
-
logs.
|
|
445
|
+
deps.log(`微信分享模块集成失败: ${wechatShareResult.error}`);
|
|
446
|
+
wechatShareResult.logs.forEach(msg => deps.log(msg));
|
|
448
447
|
}
|
|
449
448
|
}
|
|
450
449
|
if (options.wechatOauth && bundleId) {
|
|
451
|
-
|
|
450
|
+
deps.log('集成微信登录模块');
|
|
452
451
|
const wechatOauthResult = await integrateWechatOauthIOS(options.projectPath, projectName, bundleId, {
|
|
453
452
|
appId: options.wechatOauth.appId,
|
|
454
453
|
universalLinks: options.wechatOauth.universalLinks,
|
|
@@ -472,16 +471,16 @@ export async function buildIOSApp(options, deps) {
|
|
|
472
471
|
xpath: deps.xpath
|
|
473
472
|
});
|
|
474
473
|
if (wechatOauthResult.success) {
|
|
475
|
-
|
|
476
|
-
logs.
|
|
474
|
+
deps.log('微信登录模块集成完成');
|
|
475
|
+
wechatOauthResult.logs.forEach(msg => deps.log(msg));
|
|
477
476
|
}
|
|
478
477
|
else {
|
|
479
|
-
|
|
480
|
-
logs.
|
|
478
|
+
deps.log(`微信登录模块集成失败: ${wechatOauthResult.error}`);
|
|
479
|
+
wechatOauthResult.logs.forEach(msg => deps.log(msg));
|
|
481
480
|
}
|
|
482
481
|
}
|
|
483
482
|
if (options.qqShare && bundleId) {
|
|
484
|
-
|
|
483
|
+
deps.log('集成QQ分享模块');
|
|
485
484
|
const qqShareResult = await integrateQQShareIOS(options.projectPath, projectName, bundleId, {
|
|
486
485
|
appId: options.qqShare.appId,
|
|
487
486
|
universalLinks: options.qqShare.universalLinks,
|
|
@@ -505,16 +504,16 @@ export async function buildIOSApp(options, deps) {
|
|
|
505
504
|
xpath: deps.xpath
|
|
506
505
|
});
|
|
507
506
|
if (qqShareResult.success) {
|
|
508
|
-
|
|
509
|
-
logs.
|
|
507
|
+
deps.log('QQ分享模块集成完成');
|
|
508
|
+
qqShareResult.logs.forEach(msg => deps.log(msg));
|
|
510
509
|
}
|
|
511
510
|
else {
|
|
512
|
-
|
|
513
|
-
logs.
|
|
511
|
+
deps.log(`QQ分享模块集成失败: ${qqShareResult.error}`);
|
|
512
|
+
qqShareResult.logs.forEach(msg => deps.log(msg));
|
|
514
513
|
}
|
|
515
514
|
}
|
|
516
515
|
if (options.sinaShare && bundleId) {
|
|
517
|
-
|
|
516
|
+
deps.log('集成新浪微博分享模块');
|
|
518
517
|
const sinaShareResult = await integrateSinaShareIOS(options.projectPath, projectName, bundleId, {
|
|
519
518
|
appKey: options.sinaShare.appKey,
|
|
520
519
|
appSecret: options.sinaShare.appSecret,
|
|
@@ -540,16 +539,16 @@ export async function buildIOSApp(options, deps) {
|
|
|
540
539
|
xpath: deps.xpath
|
|
541
540
|
});
|
|
542
541
|
if (sinaShareResult.success) {
|
|
543
|
-
|
|
544
|
-
logs.
|
|
542
|
+
deps.log('新浪微博分享模块集成完成');
|
|
543
|
+
sinaShareResult.logs.forEach(msg => deps.log(msg));
|
|
545
544
|
}
|
|
546
545
|
else {
|
|
547
|
-
|
|
548
|
-
logs.
|
|
546
|
+
deps.log(`新浪微博分享模块集成失败: ${sinaShareResult.error}`);
|
|
547
|
+
sinaShareResult.logs.forEach(msg => deps.log(msg));
|
|
549
548
|
}
|
|
550
549
|
}
|
|
551
550
|
if (options.nativePlugins && options.nativePlugins.length > 0) {
|
|
552
|
-
|
|
551
|
+
deps.log('集成 UniApp 原生插件');
|
|
553
552
|
for (const pluginConfig of options.nativePlugins) {
|
|
554
553
|
const pluginResult = await integrateNativePluginIOS(options.projectPath, projectName, pluginConfig.pluginPath, {
|
|
555
554
|
existsSync: deps.existsSync,
|
|
@@ -566,51 +565,59 @@ export async function buildIOSApp(options, deps) {
|
|
|
566
565
|
exec: deps.exec,
|
|
567
566
|
parse: deps.parse,
|
|
568
567
|
xmlParser: deps.xmlParser,
|
|
569
|
-
xmlSerializer: deps.xmlSerializer
|
|
568
|
+
xmlSerializer: deps.xmlSerializer,
|
|
569
|
+
setTimeout: deps.setTimeout,
|
|
570
|
+
clearTimeout: deps.clearTimeout,
|
|
571
|
+
log: deps.log,
|
|
570
572
|
}, pluginConfig.parameters);
|
|
571
573
|
if (pluginResult.success) {
|
|
572
|
-
|
|
573
|
-
logs.
|
|
574
|
+
deps.log(`原生插件集成完成: ${pluginConfig.pluginPath}`);
|
|
575
|
+
pluginResult.logs.forEach(msg => deps.log(msg));
|
|
574
576
|
}
|
|
575
577
|
else {
|
|
576
|
-
|
|
577
|
-
logs.
|
|
578
|
+
deps.log(`原生插件集成失败: ${pluginResult.error}`);
|
|
579
|
+
pluginResult.logs.forEach(msg => deps.log(msg));
|
|
578
580
|
}
|
|
579
581
|
}
|
|
580
582
|
}
|
|
581
|
-
|
|
583
|
+
deps.log('步骤 9: 编译 iOS 应用');
|
|
582
584
|
const configuration = options.configuration || 'Release';
|
|
583
585
|
const scheme = options.scheme || projectName;
|
|
584
|
-
logs.push(`提示: 签名配置必须在 Xcode 中手动设置`);
|
|
585
|
-
logs.push(`提示: 请打开项目 ${projectFile},在 Signing & Capabilities 中配置 Team`);
|
|
586
586
|
if (options.signing?.teamId) {
|
|
587
|
-
|
|
587
|
+
deps.log(`签名配置: 开发团队 ID ${options.signing.teamId} 已自动配置到 project.pbxproj`);
|
|
588
588
|
}
|
|
589
589
|
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`;
|
|
590
590
|
if (options.clean) {
|
|
591
|
-
|
|
591
|
+
deps.log('清理构建目录');
|
|
592
592
|
const cleanCommand = `cd "${options.projectPath}" && xcodebuild -project "${projectFile}" -scheme "${scheme}" -destination "generic/platform=iOS" clean`;
|
|
593
593
|
await new Promise((resolve) => {
|
|
594
594
|
deps.exec(cleanCommand, (error, stdout, stderr) => {
|
|
595
595
|
if (error) {
|
|
596
|
-
|
|
596
|
+
deps.log(`清理警告: ${error.message}`);
|
|
597
597
|
}
|
|
598
598
|
if (stdout)
|
|
599
|
-
|
|
599
|
+
deps.log(`清理输出: ${stdout}`);
|
|
600
600
|
resolve();
|
|
601
601
|
});
|
|
602
602
|
});
|
|
603
603
|
}
|
|
604
|
-
|
|
604
|
+
deps.log(`执行构建命令: ${buildCommand}`);
|
|
605
|
+
deps.log(`提示: iOS 构建可能需要较长时间,请耐心等待...`);
|
|
606
|
+
deps.log(`提示: 如果超过 10 分钟没有输出,构建可能会被取消`);
|
|
607
|
+
let resolved = false;
|
|
605
608
|
const buildResult = await new Promise((resolve) => {
|
|
606
609
|
const child = deps.exec(buildCommand, (error, stdout, stderr) => {
|
|
610
|
+
if (resolved)
|
|
611
|
+
return;
|
|
612
|
+
resolved = true;
|
|
613
|
+
deps.clearTimeout(timeout);
|
|
607
614
|
const allOutput = stdout + (stderr ? '\n' + stderr : '');
|
|
608
615
|
if (error) {
|
|
609
|
-
|
|
616
|
+
deps.log(`构建错误: ${error.message}`);
|
|
610
617
|
if (stdout)
|
|
611
|
-
|
|
618
|
+
deps.log(`标准输出:\n${stdout}`);
|
|
612
619
|
if (stderr)
|
|
613
|
-
|
|
620
|
+
deps.log(`错误输出:\n${stderr}`);
|
|
614
621
|
const errorDetails = allOutput.includes('error:')
|
|
615
622
|
? allOutput.split('error:').slice(1).join('error:').split('\n').slice(0, 5).join('\n')
|
|
616
623
|
: (stderr || stdout || error.message);
|
|
@@ -622,14 +629,18 @@ export async function buildIOSApp(options, deps) {
|
|
|
622
629
|
return;
|
|
623
630
|
}
|
|
624
631
|
if (stdout)
|
|
625
|
-
|
|
632
|
+
deps.log(`构建输出:\n${stdout}`);
|
|
626
633
|
if (stderr)
|
|
627
|
-
|
|
634
|
+
deps.log(`警告信息:\n${stderr}`);
|
|
628
635
|
resolve({ success: true });
|
|
629
636
|
});
|
|
630
|
-
deps.setTimeout(() => {
|
|
637
|
+
const timeout = deps.setTimeout(() => {
|
|
638
|
+
if (resolved)
|
|
639
|
+
return;
|
|
640
|
+
resolved = true;
|
|
641
|
+
deps.log(`警告: 构建超时(10分钟),正在终止进程...`);
|
|
631
642
|
child.kill();
|
|
632
|
-
resolve({ success: false, error: '
|
|
643
|
+
resolve({ success: false, error: '构建超时(10分钟)' });
|
|
633
644
|
}, 600000);
|
|
634
645
|
});
|
|
635
646
|
if (!buildResult.success) {
|
|
@@ -639,7 +650,7 @@ export async function buildIOSApp(options, deps) {
|
|
|
639
650
|
return {
|
|
640
651
|
success: false,
|
|
641
652
|
error: errorMessage,
|
|
642
|
-
logs
|
|
653
|
+
logs: []
|
|
643
654
|
};
|
|
644
655
|
}
|
|
645
656
|
const shouldExportIPA = options.exportIPA !== false;
|
|
@@ -647,29 +658,29 @@ export async function buildIOSApp(options, deps) {
|
|
|
647
658
|
const archivePath = deps.join(buildBasePath, `${projectName}.xcarchive`);
|
|
648
659
|
if (!deps.existsSync(archivePath)) {
|
|
649
660
|
const errorMessage = `Archive 文件不存在: ${archivePath}`;
|
|
650
|
-
|
|
661
|
+
deps.log(errorMessage);
|
|
651
662
|
return {
|
|
652
663
|
success: false,
|
|
653
664
|
error: errorMessage,
|
|
654
|
-
logs
|
|
665
|
+
logs: []
|
|
655
666
|
};
|
|
656
667
|
}
|
|
657
|
-
|
|
668
|
+
deps.log(`Archive 文件已找到: ${archivePath}`);
|
|
658
669
|
if (!shouldExportIPA) {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
670
|
+
deps.log('iOS 插件项目编译完成(跳过 IPA 导出)');
|
|
671
|
+
deps.log(`Archive 文件: ${archivePath}`);
|
|
672
|
+
deps.log('\n💡 提示: 插件开发构建已完成,可以在 Xcode 中运行项目进行调试');
|
|
673
|
+
deps.log('💡 如需导出 IPA,请设置 exportIPA: true');
|
|
663
674
|
return {
|
|
664
675
|
success: true,
|
|
665
676
|
outputPath: archivePath,
|
|
666
|
-
logs
|
|
677
|
+
logs: []
|
|
667
678
|
};
|
|
668
679
|
}
|
|
669
680
|
const exportBasePath = deps.join(buildBasePath, 'export');
|
|
670
681
|
if (!deps.existsSync(exportBasePath)) {
|
|
671
682
|
deps.mkdirSync(exportBasePath, { recursive: true });
|
|
672
|
-
|
|
683
|
+
deps.log(`创建导出目录: ${exportBasePath}`);
|
|
673
684
|
}
|
|
674
685
|
const exportOptionsPlistPath = deps.join(exportBasePath, 'ExportOptions.plist');
|
|
675
686
|
const method = 'development';
|
|
@@ -694,30 +705,30 @@ export async function buildIOSApp(options, deps) {
|
|
|
694
705
|
deps.writeFileSync(exportOptionsPlistPath, exportOptionsPlistContent, 'utf8');
|
|
695
706
|
if (!deps.existsSync(exportOptionsPlistPath)) {
|
|
696
707
|
const errorMessage = `ExportOptions.plist 文件创建失败: ${exportOptionsPlistPath}`;
|
|
697
|
-
|
|
708
|
+
deps.log(errorMessage);
|
|
698
709
|
return {
|
|
699
710
|
success: false,
|
|
700
711
|
error: errorMessage,
|
|
701
|
-
logs
|
|
712
|
+
logs: []
|
|
702
713
|
};
|
|
703
714
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
715
|
+
deps.log(`ExportOptions.plist 文件已创建: ${exportOptionsPlistPath}`);
|
|
716
|
+
deps.log('开始导出 IPA');
|
|
717
|
+
deps.log(`Archive 路径: ${archivePath}`);
|
|
718
|
+
deps.log(`导出路径: ${exportBasePath}`);
|
|
719
|
+
deps.log(`ExportOptions.plist 路径: ${exportOptionsPlistPath}`);
|
|
720
|
+
deps.log(`ExportOptions.plist 内容:\n${exportOptionsPlistContent}`);
|
|
710
721
|
const exportCommand = `xcodebuild -exportArchive -archivePath "${archivePath}" -exportPath "${exportBasePath}" -exportOptionsPlist "${exportOptionsPlistPath}"`;
|
|
711
|
-
|
|
712
|
-
|
|
722
|
+
deps.log(`执行导出命令: ${exportCommand}`);
|
|
723
|
+
deps.log('注意:如果导出失败,请检查上面的日志输出,特别是 "导出标准输出" 和 "导出错误/警告输出" 部分');
|
|
713
724
|
const exportResult = await new Promise((resolve) => {
|
|
714
725
|
const child = deps.exec(exportCommand, (error, stdout, stderr) => {
|
|
715
726
|
const allOutput = stdout + (stderr ? '\n' + stderr : '');
|
|
716
727
|
if (stdout) {
|
|
717
|
-
|
|
728
|
+
deps.log(`导出标准输出:\n${stdout}`);
|
|
718
729
|
}
|
|
719
730
|
if (stderr) {
|
|
720
|
-
|
|
731
|
+
deps.log(`导出错误/警告输出:\n${stderr}`);
|
|
721
732
|
}
|
|
722
733
|
const hasError = allOutput.toLowerCase().includes('error:') ||
|
|
723
734
|
allOutput.toLowerCase().includes('failed') ||
|
|
@@ -726,7 +737,7 @@ export async function buildIOSApp(options, deps) {
|
|
|
726
737
|
allOutput.toLowerCase().includes('export succeeded') ||
|
|
727
738
|
allOutput.toLowerCase().includes('exportarchive succeeded');
|
|
728
739
|
if (error) {
|
|
729
|
-
|
|
740
|
+
deps.log(`导出命令执行错误: ${error.message}`);
|
|
730
741
|
const errorDetails = hasError
|
|
731
742
|
? allOutput.split(/error:/i).slice(1).join('error:').split('\n').slice(0, 10).join('\n')
|
|
732
743
|
: (stderr || stdout || error.message);
|
|
@@ -747,15 +758,15 @@ export async function buildIOSApp(options, deps) {
|
|
|
747
758
|
return;
|
|
748
759
|
}
|
|
749
760
|
if (hasSuccess) {
|
|
750
|
-
|
|
761
|
+
deps.log('导出命令执行成功(检测到成功标志)');
|
|
751
762
|
resolve({ success: true });
|
|
752
763
|
}
|
|
753
764
|
else if (!hasError && allOutput.trim().length > 0) {
|
|
754
|
-
|
|
765
|
+
deps.log('导出命令执行完成(未检测到错误,假设成功)');
|
|
755
766
|
resolve({ success: true });
|
|
756
767
|
}
|
|
757
768
|
else if (!hasError) {
|
|
758
|
-
|
|
769
|
+
deps.log('导出命令执行完成(无错误无输出,假设成功)');
|
|
759
770
|
resolve({ success: true });
|
|
760
771
|
}
|
|
761
772
|
else {
|
|
@@ -778,17 +789,17 @@ export async function buildIOSApp(options, deps) {
|
|
|
778
789
|
return {
|
|
779
790
|
success: false,
|
|
780
791
|
error: errorMessage,
|
|
781
|
-
logs
|
|
792
|
+
logs: []
|
|
782
793
|
};
|
|
783
794
|
}
|
|
784
795
|
let ipaPath;
|
|
785
796
|
try {
|
|
786
797
|
if (deps.existsSync(exportBasePath)) {
|
|
787
798
|
const topLevelFiles = deps.readdirSync(exportBasePath);
|
|
788
|
-
|
|
799
|
+
deps.log(`导出目录内容: ${topLevelFiles.join(', ')}`);
|
|
789
800
|
}
|
|
790
801
|
else {
|
|
791
|
-
|
|
802
|
+
deps.log(`警告: 导出目录不存在: ${exportBasePath}`);
|
|
792
803
|
}
|
|
793
804
|
const findIpaFile = (dir, depth = 0) => {
|
|
794
805
|
if (depth > 3) {
|
|
@@ -798,11 +809,11 @@ export async function buildIOSApp(options, deps) {
|
|
|
798
809
|
return undefined;
|
|
799
810
|
}
|
|
800
811
|
const files = deps.readdirSync(dir);
|
|
801
|
-
|
|
812
|
+
deps.log(`搜索目录 (深度 ${depth}): ${dir}, 文件数: ${files.length}`);
|
|
802
813
|
const ipaFile = files.find(f => f.toLowerCase().endsWith('.ipa'));
|
|
803
814
|
if (ipaFile) {
|
|
804
815
|
const foundPath = deps.join(dir, ipaFile);
|
|
805
|
-
|
|
816
|
+
deps.log(`找到 IPA 文件: ${foundPath}`);
|
|
806
817
|
return foundPath;
|
|
807
818
|
}
|
|
808
819
|
for (const file of files) {
|
|
@@ -825,7 +836,7 @@ export async function buildIOSApp(options, deps) {
|
|
|
825
836
|
ipaPath = findIpaFile(exportBasePath);
|
|
826
837
|
}
|
|
827
838
|
catch (error) {
|
|
828
|
-
|
|
839
|
+
deps.log(`查找 IPA 文件时出错: ${error instanceof Error ? error.message : String(error)}`);
|
|
829
840
|
}
|
|
830
841
|
if (!ipaPath) {
|
|
831
842
|
const listDirectory = (dir, prefix = '') => {
|
|
@@ -859,22 +870,22 @@ export async function buildIOSApp(options, deps) {
|
|
|
859
870
|
};
|
|
860
871
|
const dirStructure = listDirectory(exportBasePath);
|
|
861
872
|
const errorMessage = `导出成功但未找到 IPA 文件,导出路径: ${exportBasePath}`;
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
873
|
+
deps.log(errorMessage);
|
|
874
|
+
deps.log('导出目录结构:');
|
|
875
|
+
dirStructure.forEach(msg => deps.log(msg));
|
|
876
|
+
deps.log('请检查 xcodebuild 导出日志,确认是否有错误');
|
|
866
877
|
return {
|
|
867
878
|
success: false,
|
|
868
879
|
error: errorMessage,
|
|
869
|
-
logs
|
|
880
|
+
logs: []
|
|
870
881
|
};
|
|
871
882
|
}
|
|
872
|
-
|
|
873
|
-
|
|
883
|
+
deps.log('iOS 离线打包完成');
|
|
884
|
+
deps.log(`IPA 文件已生成: ${ipaPath}`);
|
|
874
885
|
return {
|
|
875
886
|
success: true,
|
|
876
887
|
outputPath: ipaPath,
|
|
877
|
-
logs
|
|
888
|
+
logs: []
|
|
878
889
|
};
|
|
879
890
|
}
|
|
880
891
|
catch (error) {
|
|
@@ -882,7 +893,7 @@ export async function buildIOSApp(options, deps) {
|
|
|
882
893
|
return {
|
|
883
894
|
success: false,
|
|
884
895
|
error: `打包过程中发生异常: ${errorMessage}`,
|
|
885
|
-
logs
|
|
896
|
+
logs: []
|
|
886
897
|
};
|
|
887
898
|
}
|
|
888
899
|
}
|