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.
@@ -1,84 +1,113 @@
1
- import { addFileToXcodeProject, addFileToEmbedFrameworks } from './integrateThirdPartyModule';
1
+ import { addFileToXcodeProject, addFileToEmbedFrameworks, } from "./integrateThirdPartyModule";
2
2
  async function extractPlugin(pluginPath, extractDir, deps) {
3
3
  try {
4
4
  if (deps.existsSync(pluginPath)) {
5
5
  const stat = deps.statSync(pluginPath);
6
6
  if (stat.isDirectory()) {
7
+ deps.log?.("插件是目录,直接使用");
7
8
  return {
8
9
  success: true,
9
- extractedPath: pluginPath
10
+ extractedPath: pluginPath,
10
11
  };
11
12
  }
12
13
  }
13
- if (pluginPath.endsWith('.zip')) {
14
- const pluginName = deps.basename(pluginPath, '.zip');
14
+ if (pluginPath.endsWith(".zip")) {
15
+ const pluginName = deps.basename(pluginPath, ".zip");
15
16
  const targetDir = deps.join(extractDir, pluginName);
16
17
  if (deps.existsSync(targetDir)) {
18
+ deps.log?.(`插件已解压过,使用现有目录: ${targetDir}`);
17
19
  return {
18
20
  success: true,
19
- extractedPath: targetDir
21
+ extractedPath: targetDir,
20
22
  };
21
23
  }
22
24
  if (!deps.existsSync(extractDir)) {
23
25
  deps.mkdirSync(extractDir, { recursive: true });
24
26
  }
27
+ deps.log?.(`开始解压插件: ${pluginPath}`);
28
+ deps.log?.(`解压到目录: ${extractDir}`);
25
29
  return new Promise((resolve) => {
26
- deps.exec(`unzip -q "${pluginPath}" -d "${extractDir}"`, (error, stdout, stderr) => {
30
+ let resolved = false;
31
+ let timeoutId;
32
+ const child = deps.exec(`unzip -q "${pluginPath}" -d "${extractDir}"`, (error, stdout, stderr) => {
33
+ if (resolved)
34
+ return;
35
+ resolved = true;
36
+ if (timeoutId !== undefined) {
37
+ deps.clearTimeout(timeoutId);
38
+ }
27
39
  if (error) {
40
+ deps.log?.(`解压失败: ${error.message}`);
41
+ if (stderr)
42
+ deps.log?.(`错误输出: ${stderr}`);
28
43
  resolve({
29
44
  success: false,
30
- error: `解压插件失败: ${error.message}`
45
+ error: `解压插件失败: ${error.message}`,
31
46
  });
32
47
  return;
33
48
  }
49
+ deps.log?.("解压完成,查找解压后的目录...");
34
50
  const files = deps.readdirSync(extractDir);
35
51
  if (files.length === 0) {
52
+ deps.log?.("解压后未找到任何文件");
36
53
  resolve({
37
54
  success: false,
38
- error: '解压后未找到插件文件'
55
+ error: "解压后未找到插件文件",
39
56
  });
40
57
  return;
41
58
  }
42
59
  const extractedPath = deps.join(extractDir, files[0]);
60
+ deps.log?.(`找到解压后的目录: ${extractedPath}`);
43
61
  resolve({
44
62
  success: true,
45
- extractedPath
63
+ extractedPath,
46
64
  });
47
65
  });
66
+ timeoutId = deps.setTimeout(() => {
67
+ if (resolved)
68
+ return;
69
+ resolved = true;
70
+ child.kill();
71
+ deps.log?.("解压超时(30秒)");
72
+ resolve({
73
+ success: false,
74
+ error: "解压插件超时",
75
+ });
76
+ }, 30000);
48
77
  });
49
78
  }
50
79
  return {
51
80
  success: false,
52
- error: `不支持的插件格式: ${pluginPath}`
81
+ error: `不支持的插件格式: ${pluginPath}`,
53
82
  };
54
83
  }
55
84
  catch (error) {
56
85
  return {
57
86
  success: false,
58
- error: `解压插件异常: ${error instanceof Error ? error.message : String(error)}`
87
+ error: `解压插件异常: ${error instanceof Error ? error.message : String(error)}`,
59
88
  };
60
89
  }
61
90
  }
62
91
  function readPluginPackageJson(pluginDir, deps) {
63
92
  try {
64
- const packageJsonPath = deps.join(pluginDir, 'package.json');
93
+ const packageJsonPath = deps.join(pluginDir, "package.json");
65
94
  if (!deps.existsSync(packageJsonPath)) {
66
95
  return {
67
96
  success: false,
68
- error: `插件 package.json 不存在: ${packageJsonPath}`
97
+ error: `插件 package.json 不存在: ${packageJsonPath}`,
69
98
  };
70
99
  }
71
- const content = deps.readFileSync(packageJsonPath, 'utf8');
100
+ const content = deps.readFileSync(packageJsonPath, "utf8");
72
101
  const packageJson = deps.parse(content);
73
102
  return {
74
103
  success: true,
75
- packageJson
104
+ packageJson,
76
105
  };
77
106
  }
78
107
  catch (error) {
79
108
  return {
80
109
  success: false,
81
- error: `读取插件 package.json 失败: ${error instanceof Error ? error.message : String(error)}`
110
+ error: `读取插件 package.json 失败: ${error instanceof Error ? error.message : String(error)}`,
82
111
  };
83
112
  }
84
113
  }
@@ -88,14 +117,14 @@ function extractIOSPluginConfig(packageJson) {
88
117
  if (!iosConfig) {
89
118
  return {
90
119
  success: false,
91
- error: 'package.json 中未找到 _dp_nativeplugin.ios 配置'
120
+ error: "package.json 中未找到 _dp_nativeplugin.ios 配置",
92
121
  };
93
122
  }
94
123
  const plugins = iosConfig.plugins;
95
124
  if (!plugins || !Array.isArray(plugins) || plugins.length === 0) {
96
125
  return {
97
126
  success: false,
98
- error: 'package.json 中未找到有效的 plugins 配置'
127
+ error: "package.json 中未找到有效的 plugins 配置",
99
128
  };
100
129
  }
101
130
  const pluginItems = [];
@@ -104,29 +133,31 @@ function extractIOSPluginConfig(packageJson) {
104
133
  pluginItems.push({
105
134
  type: plugin.type,
106
135
  name: plugin.name,
107
- class: plugin.class
136
+ class: plugin.class,
108
137
  });
109
138
  }
110
139
  }
111
140
  if (pluginItems.length === 0) {
112
141
  return {
113
142
  success: false,
114
- error: 'package.json 中未找到有效的插件配置'
143
+ error: "package.json 中未找到有效的插件配置",
115
144
  };
116
145
  }
117
- const hooksClass = iosConfig.hooksClass || '';
146
+ const hooksClass = iosConfig.hooksClass || "";
118
147
  const frameworks = iosConfig.frameworks || [];
119
148
  const embedFrameworks = iosConfig.embedFrameworks || [];
120
149
  const resources = iosConfig.resources || [];
121
150
  const privacies = iosConfig.privacies || [];
122
151
  let parameters = undefined;
123
- if (iosConfig.parameters && typeof iosConfig.parameters === 'object') {
152
+ if (iosConfig.parameters && typeof iosConfig.parameters === "object") {
124
153
  parameters = {};
125
154
  for (const [paramName, paramConfig] of Object.entries(iosConfig.parameters)) {
126
- if (paramConfig && typeof paramConfig === 'object' && 'key' in paramConfig) {
155
+ if (paramConfig &&
156
+ typeof paramConfig === "object" &&
157
+ "key" in paramConfig) {
127
158
  parameters[paramName] = {
128
159
  key: paramConfig.key,
129
- des: paramConfig.des || ''
160
+ des: paramConfig.des || "",
130
161
  };
131
162
  }
132
163
  }
@@ -139,18 +170,18 @@ function extractIOSPluginConfig(packageJson) {
139
170
  embedFrameworks,
140
171
  resources,
141
172
  privacies,
142
- parameters
173
+ parameters,
143
174
  };
144
175
  }
145
176
  catch (error) {
146
177
  return {
147
178
  success: false,
148
- error: `提取插件配置失败: ${error instanceof Error ? error.message : String(error)}`
179
+ error: `提取插件配置失败: ${error instanceof Error ? error.message : String(error)}`,
149
180
  };
150
181
  }
151
182
  }
152
183
  function addPluginToInfoPlist(xmlDoc, pluginItems, hooksClass) {
153
- const dictElement = xmlDoc.getElementsByTagName('dict')[0];
184
+ const dictElement = xmlDoc.getElementsByTagName("dict")[0];
154
185
  if (!dictElement)
155
186
  return false;
156
187
  let unipluginsKey = null;
@@ -158,9 +189,9 @@ function addPluginToInfoPlist(xmlDoc, pluginItems, hooksClass) {
158
189
  const childNodes = Array.from(dictElement.childNodes || []).filter((node) => node.nodeType === 1);
159
190
  for (let i = 0; i < childNodes.length; i++) {
160
191
  const node = childNodes[i];
161
- if (node.nodeName === 'key' && node.textContent === 'dcloud_uniplugins') {
192
+ if (node.nodeName === "key" && node.textContent === "dcloud_uniplugins") {
162
193
  unipluginsKey = node;
163
- if (i + 1 < childNodes.length && childNodes[i + 1].nodeName === 'array') {
194
+ if (i + 1 < childNodes.length && childNodes[i + 1].nodeName === "array") {
164
195
  unipluginsArray = childNodes[i + 1];
165
196
  break;
166
197
  }
@@ -168,40 +199,40 @@ function addPluginToInfoPlist(xmlDoc, pluginItems, hooksClass) {
168
199
  }
169
200
  if (!unipluginsArray) {
170
201
  if (!unipluginsKey) {
171
- unipluginsKey = xmlDoc.createElement('key');
172
- unipluginsKey.textContent = 'dcloud_uniplugins';
202
+ unipluginsKey = xmlDoc.createElement("key");
203
+ unipluginsKey.textContent = "dcloud_uniplugins";
173
204
  dictElement.appendChild(unipluginsKey);
174
205
  }
175
- unipluginsArray = xmlDoc.createElement('array');
206
+ unipluginsArray = xmlDoc.createElement("array");
176
207
  dictElement.appendChild(unipluginsArray);
177
208
  }
178
- const pluginDict = xmlDoc.createElement('dict');
179
- const hooksClassKey = xmlDoc.createElement('key');
180
- hooksClassKey.textContent = 'hooksClass';
181
- const hooksClassValue = xmlDoc.createElement('string');
209
+ const pluginDict = xmlDoc.createElement("dict");
210
+ const hooksClassKey = xmlDoc.createElement("key");
211
+ hooksClassKey.textContent = "hooksClass";
212
+ const hooksClassValue = xmlDoc.createElement("string");
182
213
  hooksClassValue.textContent = hooksClass;
183
214
  pluginDict.appendChild(hooksClassKey);
184
215
  pluginDict.appendChild(hooksClassValue);
185
- const pluginsKey = xmlDoc.createElement('key');
186
- pluginsKey.textContent = 'plugins';
187
- const pluginsArray = xmlDoc.createElement('array');
216
+ const pluginsKey = xmlDoc.createElement("key");
217
+ pluginsKey.textContent = "plugins";
218
+ const pluginsArray = xmlDoc.createElement("array");
188
219
  for (const plugin of pluginItems) {
189
- const itemDict = xmlDoc.createElement('dict');
190
- const typeKey = xmlDoc.createElement('key');
191
- typeKey.textContent = 'type';
192
- const typeValue = xmlDoc.createElement('string');
220
+ const itemDict = xmlDoc.createElement("dict");
221
+ const typeKey = xmlDoc.createElement("key");
222
+ typeKey.textContent = "type";
223
+ const typeValue = xmlDoc.createElement("string");
193
224
  typeValue.textContent = plugin.type;
194
225
  itemDict.appendChild(typeKey);
195
226
  itemDict.appendChild(typeValue);
196
- const nameKey = xmlDoc.createElement('key');
197
- nameKey.textContent = 'name';
198
- const nameValue = xmlDoc.createElement('string');
227
+ const nameKey = xmlDoc.createElement("key");
228
+ nameKey.textContent = "name";
229
+ const nameValue = xmlDoc.createElement("string");
199
230
  nameValue.textContent = plugin.name;
200
231
  itemDict.appendChild(nameKey);
201
232
  itemDict.appendChild(nameValue);
202
- const classKey = xmlDoc.createElement('key');
203
- classKey.textContent = 'class';
204
- const classValue = xmlDoc.createElement('string');
233
+ const classKey = xmlDoc.createElement("key");
234
+ classKey.textContent = "class";
235
+ const classValue = xmlDoc.createElement("string");
205
236
  classValue.textContent = plugin.class;
206
237
  itemDict.appendChild(classKey);
207
238
  itemDict.appendChild(classValue);
@@ -213,7 +244,7 @@ function addPluginToInfoPlist(xmlDoc, pluginItems, hooksClass) {
213
244
  return true;
214
245
  }
215
246
  function addPluginParametersToInfoPlist(xmlDoc, parameters, parameterValues) {
216
- const dictElement = xmlDoc.getElementsByTagName('dict')[0];
247
+ const dictElement = xmlDoc.getElementsByTagName("dict")[0];
217
248
  if (!dictElement)
218
249
  return false;
219
250
  for (const [paramName, paramConfig] of Object.entries(parameters)) {
@@ -221,11 +252,11 @@ function addPluginParametersToInfoPlist(xmlDoc, parameters, parameterValues) {
221
252
  if (!value)
222
253
  continue;
223
254
  const key = paramConfig.key;
224
- const keys = key.split(':');
255
+ const keys = key.split(":");
225
256
  if (keys.length === 1) {
226
- const keyElement = xmlDoc.createElement('key');
257
+ const keyElement = xmlDoc.createElement("key");
227
258
  keyElement.textContent = keys[0];
228
- const valueElement = xmlDoc.createElement('string');
259
+ const valueElement = xmlDoc.createElement("string");
229
260
  valueElement.textContent = value;
230
261
  dictElement.appendChild(keyElement);
231
262
  dictElement.appendChild(valueElement);
@@ -237,23 +268,24 @@ function addPluginParametersToInfoPlist(xmlDoc, parameters, parameterValues) {
237
268
  const childNodes = Array.from(dictElement.childNodes || []).filter((node) => node.nodeType === 1);
238
269
  for (let i = 0; i < childNodes.length; i++) {
239
270
  const node = childNodes[i];
240
- if (node.nodeName === 'key' && node.textContent === parentKey) {
241
- if (i + 1 < childNodes.length && childNodes[i + 1].nodeName === 'dict') {
271
+ if (node.nodeName === "key" && node.textContent === parentKey) {
272
+ if (i + 1 < childNodes.length &&
273
+ childNodes[i + 1].nodeName === "dict") {
242
274
  parentDict = childNodes[i + 1];
243
275
  break;
244
276
  }
245
277
  }
246
278
  }
247
279
  if (!parentDict) {
248
- const parentKeyElement = xmlDoc.createElement('key');
280
+ const parentKeyElement = xmlDoc.createElement("key");
249
281
  parentKeyElement.textContent = parentKey;
250
- parentDict = xmlDoc.createElement('dict');
282
+ parentDict = xmlDoc.createElement("dict");
251
283
  dictElement.appendChild(parentKeyElement);
252
284
  dictElement.appendChild(parentDict);
253
285
  }
254
- const childKeyElement = xmlDoc.createElement('key');
286
+ const childKeyElement = xmlDoc.createElement("key");
255
287
  childKeyElement.textContent = childKey;
256
- const childValueElement = xmlDoc.createElement('string');
288
+ const childValueElement = xmlDoc.createElement("string");
257
289
  childValueElement.textContent = value;
258
290
  parentDict.appendChild(childKeyElement);
259
291
  parentDict.appendChild(childValueElement);
@@ -262,11 +294,11 @@ function addPluginParametersToInfoPlist(xmlDoc, parameters, parameterValues) {
262
294
  return true;
263
295
  }
264
296
  function addPrivaciesToInfoPlist(xmlDoc, privacies) {
265
- const dictElement = xmlDoc.getElementsByTagName('dict')[0];
297
+ const dictElement = xmlDoc.getElementsByTagName("dict")[0];
266
298
  if (!dictElement)
267
299
  return false;
268
300
  for (const privacy of privacies) {
269
- const keyElements = xmlDoc.getElementsByTagName('key');
301
+ const keyElements = xmlDoc.getElementsByTagName("key");
270
302
  let found = false;
271
303
  for (let i = 0; i < keyElements.length; i++) {
272
304
  const keyElement = keyElements[i];
@@ -276,47 +308,195 @@ function addPrivaciesToInfoPlist(xmlDoc, privacies) {
276
308
  }
277
309
  }
278
310
  if (!found) {
279
- const keyElement = xmlDoc.createElement('key');
311
+ const keyElement = xmlDoc.createElement("key");
280
312
  keyElement.textContent = privacy;
281
- const valueElement = xmlDoc.createElement('string');
282
- valueElement.textContent = '应用需要使用此功能';
313
+ const valueElement = xmlDoc.createElement("string");
314
+ valueElement.textContent = "应用需要使用此功能";
283
315
  dictElement.appendChild(keyElement);
284
316
  dictElement.appendChild(valueElement);
285
317
  }
286
318
  }
287
319
  return true;
288
320
  }
289
- function findFilesRecursive(dir, extensions, deps) {
321
+ function findFilesRecursive(dir, extensions, deps, depth = 0) {
290
322
  const result = [];
323
+ const maxDepth = 10;
291
324
  if (!deps.existsSync(dir)) {
292
325
  return result;
293
326
  }
294
- const files = deps.readdirSync(dir);
295
- for (const file of files) {
296
- const filePath = deps.join(dir, file);
297
- const stat = deps.statSync(filePath);
298
- if (stat.isDirectory()) {
299
- result.push(...findFilesRecursive(filePath, extensions, deps));
300
- }
301
- else {
302
- for (const ext of extensions) {
303
- if (file.endsWith(ext)) {
304
- result.push(filePath);
305
- break;
327
+ const bundleExtensions = [".framework", ".xcframework", ".app", ".bundle"];
328
+ if (depth > maxDepth) {
329
+ return result;
330
+ }
331
+ try {
332
+ const files = deps.readdirSync(dir);
333
+ for (const file of files) {
334
+ const filePath = deps.join(dir, file);
335
+ try {
336
+ const stat = deps.statSync(filePath);
337
+ if (stat.isDirectory()) {
338
+ let matchesExtension = false;
339
+ let isBundle = false;
340
+ for (const ext of extensions) {
341
+ if (file.endsWith(ext)) {
342
+ matchesExtension = true;
343
+ isBundle = bundleExtensions.includes(ext);
344
+ result.push(filePath);
345
+ break;
346
+ }
347
+ }
348
+ if (!matchesExtension || !isBundle) {
349
+ if (!matchesExtension) {
350
+ result.push(...findFilesRecursive(filePath, extensions, deps, depth + 1));
351
+ }
352
+ }
353
+ }
354
+ else {
355
+ for (const ext of extensions) {
356
+ if (file.endsWith(ext)) {
357
+ result.push(filePath);
358
+ break;
359
+ }
360
+ }
306
361
  }
307
362
  }
363
+ catch (error) {
364
+ continue;
365
+ }
308
366
  }
309
367
  }
368
+ catch (error) {
369
+ }
310
370
  return result;
311
371
  }
372
+ async function copyFrameworkUsingArchive(sourcePath, targetPath, deps, logFn) {
373
+ const log = (msg) => {
374
+ const message = `[copyFramework] ${msg}`;
375
+ if (logFn)
376
+ logFn(message);
377
+ };
378
+ try {
379
+ log(`开始复制 framework: ${deps.basename(sourcePath)}`);
380
+ log(` 源路径: ${sourcePath}`);
381
+ log(` 目标路径: ${targetPath}`);
382
+ const targetDir = deps.dirname(targetPath);
383
+ const tempDir = deps.join(targetDir, ".temp_framework_copy");
384
+ log(` 临时目录: ${tempDir}`);
385
+ if (deps.existsSync(tempDir)) {
386
+ log(` 清理已存在的临时目录...`);
387
+ await new Promise((resolve) => {
388
+ deps.exec(`rm -rf "${tempDir}"`, (error) => {
389
+ if (error) {
390
+ log(` 警告: 清理临时目录失败: ${error.message}`);
391
+ }
392
+ else {
393
+ log(` 临时目录已清理`);
394
+ }
395
+ resolve();
396
+ });
397
+ });
398
+ }
399
+ if (!deps.existsSync(tempDir)) {
400
+ log(` 创建临时目录...`);
401
+ deps.mkdirSync(tempDir, { recursive: true });
402
+ }
403
+ const frameworkName = deps.basename(sourcePath);
404
+ const archiveName = `${frameworkName}.tar.gz`;
405
+ const archivePath = deps.join(tempDir, archiveName);
406
+ log(` 压缩文件路径: ${archivePath}`);
407
+ const sourceDir = deps.dirname(sourcePath);
408
+ const sourceName = deps.basename(sourcePath);
409
+ log(` 开始压缩: ${sourceDir}/${sourceName} -> ${archivePath}`);
410
+ return new Promise((resolve) => {
411
+ const startTime = Date.now();
412
+ deps.exec(`cd "${sourceDir}" && tar -czf "${archivePath}" "${sourceName}"`, (error, stdout, stderr) => {
413
+ const compressTime = Date.now() - startTime;
414
+ log(` 压缩完成 (耗时: ${compressTime}ms)`);
415
+ if (error) {
416
+ log(` 压缩失败: ${error.message}`);
417
+ if (stderr)
418
+ log(` stderr: ${stderr}`);
419
+ resolve({
420
+ success: false,
421
+ error: `压缩 framework 失败: ${error.message}`,
422
+ });
423
+ return;
424
+ }
425
+ const targetArchivePath = deps.join(targetDir, archiveName);
426
+ log(` 开始复制压缩文件: ${archivePath} -> ${targetArchivePath}`);
427
+ const copyStartTime = Date.now();
428
+ try {
429
+ deps.copyFileSync(archivePath, targetArchivePath);
430
+ const copyTime = Date.now() - copyStartTime;
431
+ log(` 复制压缩文件完成 (耗时: ${copyTime}ms)`);
432
+ }
433
+ catch (copyError) {
434
+ log(` 复制压缩文件失败: ${copyError.message || String(copyError)}`);
435
+ resolve({
436
+ success: false,
437
+ error: `复制压缩文件失败: ${copyError.message || String(copyError)}`,
438
+ });
439
+ return;
440
+ }
441
+ log(` 开始解压: ${targetArchivePath} -> ${targetDir}`);
442
+ const extractStartTime = Date.now();
443
+ deps.exec(`cd "${targetDir}" && tar -xzf "${targetArchivePath}" && rm -f "${targetArchivePath}"`, (extractError, extractStdout, extractStderr) => {
444
+ const extractTime = Date.now() - extractStartTime;
445
+ log(` 解压完成 (耗时: ${extractTime}ms)`);
446
+ try {
447
+ if (deps.existsSync(archivePath)) {
448
+ deps.exec(`rm -f "${archivePath}"`, () => { });
449
+ }
450
+ }
451
+ catch { }
452
+ if (extractError) {
453
+ log(` 解压失败: ${extractError.message}`);
454
+ if (extractStderr)
455
+ log(` stderr: ${extractStderr}`);
456
+ resolve({
457
+ success: false,
458
+ error: `解压 framework 失败: ${extractError.message}`,
459
+ });
460
+ }
461
+ else {
462
+ const totalTime = Date.now() - startTime;
463
+ log(` framework 复制成功 (总耗时: ${totalTime}ms)`);
464
+ resolve({ success: true });
465
+ }
466
+ });
467
+ });
468
+ });
469
+ }
470
+ catch (error) {
471
+ log(` 复制 framework 异常: ${error.message || String(error)}`);
472
+ return {
473
+ success: false,
474
+ error: `复制 framework 失败: ${error.message || String(error)}`,
475
+ };
476
+ }
477
+ }
312
478
  export async function integrateNativePluginIOS(projectPath, projectName, pluginPath, deps, parameters) {
313
- const logs = [];
314
479
  try {
315
- logs.push(`开始集成 UniApp 原生插件: ${pluginPath}`);
316
- logs.push('步骤 1: 解压插件');
317
- const tempDir = deps.join(projectPath, '.temp');
480
+ deps.log?.(`开始集成 UniApp 原生插件: ${pluginPath}`);
481
+ deps.log?.("步骤 1: 解压插件");
482
+ const tempDir = deps.join(projectPath, ".temp");
483
+ if (deps.existsSync(tempDir)) {
484
+ deps.log?.("清理已存在的临时目录...");
485
+ await new Promise((resolve) => {
486
+ deps.exec(`rm -rf "${tempDir}"`, (error) => {
487
+ if (error) {
488
+ deps.log?.(`警告: 清理临时目录失败: ${error.message}`);
489
+ }
490
+ else {
491
+ deps.log?.("临时目录已清理");
492
+ }
493
+ resolve();
494
+ });
495
+ });
496
+ }
318
497
  if (!deps.existsSync(tempDir)) {
319
498
  deps.mkdirSync(tempDir, { recursive: true });
499
+ deps.log?.("已创建临时目录");
320
500
  }
321
501
  const extractResult = await extractPlugin(pluginPath, tempDir, {
322
502
  existsSync: deps.existsSync,
@@ -326,60 +506,69 @@ export async function integrateNativePluginIOS(projectPath, projectName, pluginP
326
506
  exec: deps.exec,
327
507
  basename: deps.basename,
328
508
  dirname: deps.dirname,
329
- mkdirSync: deps.mkdirSync
509
+ mkdirSync: deps.mkdirSync,
510
+ log: deps.log,
511
+ setTimeout: deps.setTimeout,
512
+ clearTimeout: deps.clearTimeout,
330
513
  });
331
514
  if (!extractResult.success) {
332
515
  return {
333
516
  success: false,
334
517
  error: extractResult.error,
335
- logs
518
+ logs: [],
336
519
  };
337
520
  }
338
521
  const pluginDir = extractResult.extractedPath;
339
- logs.push(`插件已解压到: ${pluginDir}`);
340
- logs.push('步骤 2: 读取插件配置');
522
+ deps.log?.(`插件已解压到: ${pluginDir}`);
523
+ deps.log?.("步骤 2: 读取插件配置");
341
524
  const packageJsonResult = readPluginPackageJson(pluginDir, {
342
525
  existsSync: deps.existsSync,
343
526
  readFileSync: deps.readFileSync,
344
527
  join: deps.join,
345
- parse: deps.parse
528
+ parse: deps.parse,
346
529
  });
347
530
  if (!packageJsonResult.success) {
348
531
  return {
349
532
  success: false,
350
533
  error: packageJsonResult.error,
351
- logs
534
+ logs: [],
352
535
  };
353
536
  }
354
537
  const packageJson = packageJsonResult.packageJson;
355
- logs.push(`插件名称: ${packageJson.name}`);
356
- logs.push(`插件 ID: ${packageJson.id}`);
357
- logs.push(`插件版本: ${packageJson.version}`);
358
- logs.push('步骤 3: 提取 iOS 插件配置');
538
+ deps.log?.(`插件名称: ${packageJson.name}`);
539
+ deps.log?.(`插件 ID: ${packageJson.id}`);
540
+ deps.log?.(`插件版本: ${packageJson.version}`);
541
+ deps.log?.("步骤 3: 提取 iOS 插件配置");
359
542
  const configResult = extractIOSPluginConfig(packageJson);
360
543
  if (!configResult.success) {
361
544
  return {
362
545
  success: false,
363
546
  error: configResult.error,
364
- logs
547
+ logs: [],
365
548
  };
366
549
  }
367
- const { plugins: pluginItems, hooksClass, frameworks, embedFrameworks, resources, privacies, parameters: pluginParameters } = configResult;
368
- logs.push(`找到 ${pluginItems.length} 个插件`);
550
+ const { plugins: pluginItems, hooksClass, frameworks, embedFrameworks, resources, privacies, parameters: pluginParameters, } = configResult;
551
+ deps.log?.(`找到 ${pluginItems.length} 个插件`);
369
552
  if (hooksClass) {
370
- logs.push(`Hooks 类: ${hooksClass}`);
553
+ deps.log?.(`Hooks 类: ${hooksClass}`);
371
554
  }
372
- logs.push('步骤 4: 复制插件文件');
373
- const iosDir = deps.join(pluginDir, 'ios');
555
+ deps.log?.("步骤 4: 复制插件文件");
556
+ const iosDir = deps.join(pluginDir, "ios");
557
+ deps.log?.(` iosDir: ${iosDir}`);
558
+ deps.log?.(` iosDir 存在: ${deps.existsSync(iosDir)}`);
374
559
  if (!deps.existsSync(iosDir)) {
375
560
  return {
376
561
  success: false,
377
562
  error: `插件 ios 目录不存在: ${iosDir}`,
378
- logs
563
+ logs: [],
379
564
  };
380
565
  }
381
- const staticLibs = findFilesRecursive(iosDir, ['.a'], deps);
382
- const libsDir = deps.join(projectPath, 'libs');
566
+ deps.log?.("步骤 4.1: 查找静态库 (.a)");
567
+ const findLibStartTime = Date.now();
568
+ const staticLibs = findFilesRecursive(iosDir, [".a"], deps);
569
+ const findLibTime = Date.now() - findLibStartTime;
570
+ deps.log?.(` 找到 ${staticLibs.length} 个静态库 (查找耗时: ${findLibTime}ms)`);
571
+ const libsDir = deps.join(projectPath, "libs");
383
572
  if (!deps.existsSync(libsDir)) {
384
573
  deps.mkdirSync(libsDir, { recursive: true });
385
574
  }
@@ -387,44 +576,68 @@ export async function integrateNativePluginIOS(projectPath, projectName, pluginP
387
576
  const libName = deps.basename(libPath);
388
577
  const targetPath = deps.join(libsDir, libName);
389
578
  deps.copyFileSync(libPath, targetPath);
390
- logs.push(`已复制静态库: ${libName}`);
391
- }
392
- const staticFrameworks = findFilesRecursive(iosDir, ['.framework'], deps).filter(f => {
393
- const frameworkName = deps.basename(f);
394
- return !embedFrameworks?.includes(frameworkName);
395
- });
396
- const frameworksDir = deps.join(projectPath, 'Frameworks');
579
+ deps.log?.(`已复制静态库: ${libName}`);
580
+ }
581
+ deps.log?.("步骤 4.2: 查找 framework");
582
+ deps.log?.(` 搜索目录: ${iosDir}`);
583
+ const findFrameworkStartTime = Date.now();
584
+ const allFrameworks = findFilesRecursive(iosDir, [".framework"], deps);
585
+ const findFrameworkTime = Date.now() - findFrameworkStartTime;
586
+ deps.log?.(`找到 ${allFrameworks.length} 个 framework (查找耗时: ${findFrameworkTime}ms)`);
587
+ const frameworksDir = deps.join(projectPath, "Frameworks");
397
588
  if (!deps.existsSync(frameworksDir)) {
398
589
  deps.mkdirSync(frameworksDir, { recursive: true });
399
590
  }
400
- for (const frameworkPath of staticFrameworks) {
591
+ for (const frameworkPath of allFrameworks) {
401
592
  const frameworkName = deps.basename(frameworkPath);
593
+ deps.log?.(`开始复制 framework: ${frameworkName}`);
402
594
  const targetPath = deps.join(frameworksDir, frameworkName);
403
- await deps.cp(frameworkPath, targetPath, { recursive: true, force: true });
404
- logs.push(`已复制静态 framework: ${frameworkName}`);
405
- }
406
- if (embedFrameworks && embedFrameworks.length > 0) {
407
- for (const frameworkName of embedFrameworks) {
408
- const frameworkPath = deps.join(iosDir, frameworkName);
409
- if (deps.existsSync(frameworkPath)) {
410
- const targetPath = deps.join(frameworksDir, frameworkName);
411
- await deps.cp(frameworkPath, targetPath, { recursive: true, force: true });
412
- logs.push(`已复制动态 framework: ${frameworkName}`);
413
- }
414
- else {
415
- logs.push(`警告: 动态 framework 不存在: ${frameworkPath}`);
416
- }
595
+ const copyResult = await copyFrameworkUsingArchive(frameworkPath, targetPath, {
596
+ existsSync: deps.existsSync,
597
+ readdirSync: deps.readdirSync,
598
+ join: deps.join,
599
+ dirname: deps.dirname,
600
+ exec: deps.exec,
601
+ basename: deps.basename,
602
+ mkdirSync: deps.mkdirSync,
603
+ copyFileSync: deps.copyFileSync,
604
+ }, deps.log);
605
+ if (copyResult.success) {
606
+ deps.log?.(`已复制 framework: ${frameworkName}`);
607
+ }
608
+ else {
609
+ deps.log?.(`警告: 复制 framework 失败 (${frameworkName}): ${copyResult.error}`);
417
610
  }
418
611
  }
419
- const xcframeworks = findFilesRecursive(iosDir, ['.xcframework'], deps);
612
+ deps.log?.("步骤 4.4: 查找 xcframework");
613
+ const findXcframeworkStartTime = Date.now();
614
+ const xcframeworks = findFilesRecursive(iosDir, [".xcframework"], deps);
615
+ const findXcframeworkTime = Date.now() - findXcframeworkStartTime;
616
+ deps.log?.(` 找到 ${xcframeworks.length} 个 xcframework (查找耗时: ${findXcframeworkTime}ms)`);
420
617
  for (const xcframeworkPath of xcframeworks) {
421
618
  const xcframeworkName = deps.basename(xcframeworkPath);
422
619
  const targetPath = deps.join(frameworksDir, xcframeworkName);
423
- await deps.cp(xcframeworkPath, targetPath, { recursive: true, force: true });
424
- logs.push(`已复制 xcframework: ${xcframeworkName}`);
620
+ deps.log?.(`开始复制 xcframework: ${xcframeworkName}`);
621
+ const copyResult = await copyFrameworkUsingArchive(xcframeworkPath, targetPath, {
622
+ existsSync: deps.existsSync,
623
+ readdirSync: deps.readdirSync,
624
+ join: deps.join,
625
+ dirname: deps.dirname,
626
+ exec: deps.exec,
627
+ basename: deps.basename,
628
+ mkdirSync: deps.mkdirSync,
629
+ copyFileSync: deps.copyFileSync,
630
+ }, deps.log);
631
+ if (copyResult.success) {
632
+ deps.log?.(`已复制 xcframework: ${xcframeworkName}`);
633
+ }
634
+ else {
635
+ deps.log?.(`警告: 复制 xcframework 失败 (${xcframeworkName}): ${copyResult.error}`);
636
+ }
425
637
  }
638
+ deps.log?.("步骤 4.5: 复制资源文件");
426
639
  if (resources && resources.length > 0) {
427
- const resourcesTargetDir = deps.join(projectPath, projectName, 'Resources');
640
+ const resourcesTargetDir = deps.join(projectPath, projectName, "Resources");
428
641
  if (!deps.existsSync(resourcesTargetDir)) {
429
642
  deps.mkdirSync(resourcesTargetDir, { recursive: true });
430
643
  }
@@ -435,20 +648,27 @@ export async function integrateNativePluginIOS(projectPath, projectName, pluginP
435
648
  const targetPath = deps.join(resourcesTargetDir, resourceName);
436
649
  const stat = deps.statSync(sourcePath);
437
650
  if (stat.isDirectory()) {
438
- await deps.cp(sourcePath, targetPath, { recursive: true, force: true });
651
+ await deps.cp(sourcePath, targetPath, {
652
+ recursive: true,
653
+ force: true,
654
+ });
439
655
  }
440
656
  else {
441
657
  deps.copyFileSync(sourcePath, targetPath);
442
658
  }
443
- logs.push(`已复制资源文件: ${resourceName}`);
659
+ deps.log?.(`已复制资源文件: ${resourceName}`);
444
660
  }
445
661
  else {
446
- logs.push(`警告: 资源文件不存在: ${sourcePath}`);
662
+ deps.log?.(`警告: 资源文件不存在: ${sourcePath}`);
447
663
  }
448
664
  }
449
665
  }
450
- const headers = findFilesRecursive(iosDir, ['.h'], deps);
451
- const headersDir = deps.join(projectPath, projectName, 'NativePlugins');
666
+ deps.log?.("步骤 4.6: 查找头文件 (.h)");
667
+ const findHeaderStartTime = Date.now();
668
+ const headers = findFilesRecursive(iosDir, [".h"], deps);
669
+ const findHeaderTime = Date.now() - findHeaderStartTime;
670
+ deps.log?.(` 找到 ${headers.length} 个头文件 (查找耗时: ${findHeaderTime}ms)`);
671
+ const headersDir = deps.join(projectPath, projectName, "NativePlugins");
452
672
  if (headers.length > 0) {
453
673
  if (!deps.existsSync(headersDir)) {
454
674
  deps.mkdirSync(headersDir, { recursive: true });
@@ -457,140 +677,317 @@ export async function integrateNativePluginIOS(projectPath, projectName, pluginP
457
677
  const headerName = deps.basename(headerPath);
458
678
  const targetPath = deps.join(headersDir, headerName);
459
679
  deps.copyFileSync(headerPath, targetPath);
460
- logs.push(`已复制头文件: ${headerName}`);
680
+ deps.log?.(`已复制头文件: ${headerName}`);
461
681
  }
462
682
  }
463
- logs.push('步骤 5: 修改 Info.plist');
683
+ deps.log?.("步骤 5: 修改 Info.plist");
464
684
  const infoPlistPath = deps.join(projectPath, projectName, `${projectName}-Info.plist`);
465
685
  if (deps.existsSync(infoPlistPath)) {
466
686
  try {
467
- const xmlContent = deps.readFileSync(infoPlistPath, 'utf8');
687
+ const xmlContent = deps.readFileSync(infoPlistPath, "utf8");
468
688
  const parser = new deps.xmlParser();
469
- const xmlDoc = parser.parseFromString(xmlContent, 'text/xml');
470
- addPluginToInfoPlist(xmlDoc, pluginItems, hooksClass || '');
471
- logs.push('已添加插件信息到 dcloud_uniplugins');
689
+ const xmlDoc = parser.parseFromString(xmlContent, "text/xml");
690
+ addPluginToInfoPlist(xmlDoc, pluginItems, hooksClass || "");
691
+ deps.log?.("已添加插件信息到 dcloud_uniplugins");
472
692
  if (privacies && privacies.length > 0) {
473
693
  addPrivaciesToInfoPlist(xmlDoc, privacies);
474
- logs.push(`已添加 ${privacies.length} 个隐私权限描述`);
694
+ deps.log?.(`已添加 ${privacies.length} 个隐私权限描述`);
475
695
  }
476
696
  if (pluginParameters && parameters) {
477
697
  addPluginParametersToInfoPlist(xmlDoc, pluginParameters, parameters);
478
- logs.push('已添加插件参数配置');
698
+ deps.log?.("已添加插件参数配置");
479
699
  }
480
700
  const serializer = new deps.xmlSerializer();
481
701
  const newXmlContent = serializer.serializeToString(xmlDoc);
482
- deps.writeFileSync(infoPlistPath, newXmlContent, 'utf8');
483
- logs.push('Info.plist 修改完成');
702
+ deps.writeFileSync(infoPlistPath, newXmlContent, "utf8");
703
+ deps.log?.("Info.plist 修改完成");
484
704
  }
485
705
  catch (error) {
486
- logs.push(`修改 Info.plist 失败: ${error instanceof Error ? error.message : String(error)}`);
706
+ deps.log?.(`修改 Info.plist 失败: ${error instanceof Error ? error.message : String(error)}`);
487
707
  }
488
708
  }
489
- logs.push('步骤 6: 添加文件到 Xcode 项目');
490
- const projectFiles = deps.readdirSync(projectPath).filter(file => file.endsWith('.xcodeproj'));
709
+ deps.log?.("步骤 6: 添加文件到 Xcode 项目");
710
+ const projectFiles = deps
711
+ .readdirSync(projectPath)
712
+ .filter((file) => file.endsWith(".xcodeproj"));
491
713
  if (projectFiles.length === 0) {
492
- logs.push('警告: 未找到 .xcodeproj 文件,跳过 Xcode 项目配置');
714
+ deps.log?.("警告: 未找到 .xcodeproj 文件,跳过 Xcode 项目配置");
493
715
  }
494
716
  else {
495
717
  const projectFile = projectFiles[0];
496
- const projectPbxprojPath = deps.join(projectPath, projectFile, 'project.pbxproj');
718
+ const projectPbxprojPath = deps.join(projectPath, projectFile, "project.pbxproj");
497
719
  for (const libPath of staticLibs) {
498
720
  const libName = deps.basename(libPath);
499
721
  const relativePath = `libs/${libName}`;
500
- const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, 'staticLibrary', {
722
+ const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, "staticLibrary", {
501
723
  existsSync: deps.existsSync,
502
724
  readFileSync: deps.readFileSync,
503
- writeFileSync: deps.writeFileSync
725
+ writeFileSync: deps.writeFileSync,
504
726
  });
505
727
  if (addResult.success) {
506
- logs.push(`已添加到 Xcode 项目: ${libName}`);
728
+ deps.log?.(`已添加到 Xcode 项目: ${libName}`);
507
729
  }
508
730
  else {
509
- logs.push(`警告: 添加到 Xcode 项目失败: ${addResult.error}`);
731
+ deps.log?.(`警告: 添加到 Xcode 项目失败: ${addResult.error}`);
510
732
  }
511
733
  }
512
- for (const frameworkPath of staticFrameworks) {
734
+ const embedFrameworkNames = new Set((embedFrameworks || []).map((name) => {
735
+ return name.endsWith(".framework") ? name : `${name}.framework`;
736
+ }));
737
+ const frameworksToEmbed = [];
738
+ const frameworksToLink = [];
739
+ for (const frameworkPath of allFrameworks) {
513
740
  const frameworkName = deps.basename(frameworkPath);
514
- const relativePath = `Frameworks/${frameworkName}`;
515
- const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, 'framework', {
516
- existsSync: deps.existsSync,
517
- readFileSync: deps.readFileSync,
518
- writeFileSync: deps.writeFileSync
519
- });
520
- if (addResult.success) {
521
- logs.push(`已添加到 Xcode 项目: ${frameworkName}`);
741
+ if (embedFrameworkNames.has(frameworkName)) {
742
+ frameworksToEmbed.push(frameworkPath);
522
743
  }
523
744
  else {
524
- logs.push(`警告: 添加到 Xcode 项目失败: ${addResult.error}`);
745
+ frameworksToLink.push(frameworkPath);
746
+ }
747
+ }
748
+ if (frameworksToEmbed.length > 0) {
749
+ deps.log?.(`步骤 6.2.1: 添加 ${frameworksToEmbed.length} 个 framework 到 Link Binary With Libraries 和 Embed Frameworks`);
750
+ for (const frameworkPath of frameworksToEmbed) {
751
+ const frameworkName = deps.basename(frameworkPath);
752
+ const relativePath = `Frameworks/${frameworkName}`;
753
+ const linkResult = addFileToXcodeProject(projectPbxprojPath, relativePath, "framework", {
754
+ existsSync: deps.existsSync,
755
+ readFileSync: deps.readFileSync,
756
+ writeFileSync: deps.writeFileSync,
757
+ });
758
+ if (!linkResult.success) {
759
+ deps.log?.(`警告: 添加到 Link Binary With Libraries 失败: ${linkResult.error}`);
760
+ }
761
+ const embedResult = addFileToEmbedFrameworks(projectPbxprojPath, relativePath, {
762
+ existsSync: deps.existsSync,
763
+ readFileSync: deps.readFileSync,
764
+ writeFileSync: deps.writeFileSync,
765
+ });
766
+ if (embedResult.success) {
767
+ deps.log?.(`已添加到 Embed Frameworks: ${frameworkName}`);
768
+ }
769
+ else {
770
+ deps.log?.(`警告: 添加到 Embed Frameworks 失败: ${embedResult.error}`);
771
+ }
772
+ }
773
+ }
774
+ if (frameworksToLink.length > 0) {
775
+ deps.log?.(`步骤 6.2.2: 添加 ${frameworksToLink.length} 个 framework 到 Link Binary With Libraries`);
776
+ for (const frameworkPath of frameworksToLink) {
777
+ const frameworkName = deps.basename(frameworkPath);
778
+ const relativePath = `Frameworks/${frameworkName}`;
779
+ const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, "framework", {
780
+ existsSync: deps.existsSync,
781
+ readFileSync: deps.readFileSync,
782
+ writeFileSync: deps.writeFileSync,
783
+ });
784
+ if (addResult.success) {
785
+ deps.log?.(`已添加到 Link Binary With Libraries: ${frameworkName}`);
786
+ }
787
+ else {
788
+ deps.log?.(`警告: 添加到 Link Binary With Libraries 失败: ${addResult.error}`);
789
+ }
525
790
  }
526
791
  }
527
792
  for (const xcframeworkPath of xcframeworks) {
528
793
  const xcframeworkName = deps.basename(xcframeworkPath);
529
794
  const relativePath = `Frameworks/${xcframeworkName}`;
530
- const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, 'framework', {
795
+ const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, "framework", {
531
796
  existsSync: deps.existsSync,
532
797
  readFileSync: deps.readFileSync,
533
- writeFileSync: deps.writeFileSync
798
+ writeFileSync: deps.writeFileSync,
534
799
  });
535
800
  if (addResult.success) {
536
- logs.push(`已添加到 Xcode 项目: ${xcframeworkName}`);
801
+ deps.log?.(`已添加到 Xcode 项目: ${xcframeworkName}`);
537
802
  }
538
803
  else {
539
- logs.push(`警告: 添加到 Xcode 项目失败: ${addResult.error}`);
804
+ deps.log?.(`警告: 添加到 Xcode 项目失败: ${addResult.error}`);
540
805
  }
541
806
  }
542
807
  if (resources && resources.length > 0) {
543
808
  for (const resourcePath of resources) {
544
809
  const resourceName = deps.basename(resourcePath);
545
810
  const relativePath = `${projectName}/Resources/${resourceName}`;
546
- const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, 'bundle', {
811
+ const addResult = addFileToXcodeProject(projectPbxprojPath, relativePath, "bundle", {
547
812
  existsSync: deps.existsSync,
548
813
  readFileSync: deps.readFileSync,
549
- writeFileSync: deps.writeFileSync
814
+ writeFileSync: deps.writeFileSync,
550
815
  });
551
816
  if (addResult.success) {
552
- logs.push(`已添加资源到 Xcode 项目: ${resourceName}`);
817
+ deps.log?.(`已添加资源到 Xcode 项目: ${resourceName}`);
553
818
  }
554
819
  else {
555
- logs.push(`警告: 添加资源到 Xcode 项目失败: ${addResult.error}`);
820
+ deps.log?.(`警告: 添加资源到 Xcode 项目失败: ${addResult.error}`);
556
821
  }
557
822
  }
558
823
  }
559
- if (embedFrameworks && embedFrameworks.length > 0) {
560
- for (const frameworkName of embedFrameworks) {
561
- const relativePath = `Frameworks/${frameworkName}`;
562
- const addResult = addFileToEmbedFrameworks(projectPbxprojPath, relativePath, {
563
- existsSync: deps.existsSync,
564
- readFileSync: deps.readFileSync,
565
- writeFileSync: deps.writeFileSync
566
- });
567
- if (addResult.success) {
568
- logs.push(`已添加动态 framework 到 Embed Frameworks: ${frameworkName}`);
824
+ if (frameworks && frameworks.length > 0) {
825
+ deps.log?.("注意: 系统库需要手动在 Xcode 中添加到 Link Binary With Libraries:");
826
+ for (const framework of frameworks) {
827
+ deps.log?.(` - ${framework}`);
828
+ }
829
+ }
830
+ deps.log?.("步骤 6.8: 检查插件依赖");
831
+ const pluginFrameworkDir = deps.join(pluginDir, "ios");
832
+ if (deps.existsSync(pluginFrameworkDir)) {
833
+ try {
834
+ const frameworkFiles = findFilesRecursive(pluginFrameworkDir, [".m", ".mm", ".swift"], deps);
835
+ let hasSVGKitImport = false;
836
+ for (const file of frameworkFiles) {
837
+ try {
838
+ const content = deps.readFileSync(file, "utf8");
839
+ if (content.includes("SVGKit") || content.includes("SVGKImage")) {
840
+ hasSVGKitImport = true;
841
+ break;
842
+ }
843
+ }
844
+ catch {
845
+ }
569
846
  }
570
- else {
571
- logs.push(`警告: 添加动态 framework 失败: ${addResult.error}`);
847
+ if (hasSVGKitImport) {
848
+ deps.log?.("⚠️ 警告: 插件使用了 SVGKit 库,但主项目中可能未包含该库");
849
+ deps.log?.(" 解决方案 1: 在主项目中使用 CocoaPods 安装 SVGKit");
850
+ deps.log?.(' 1. 在主项目根目录创建 Podfile,添加: pod "SVGKit", "~> 3.0"');
851
+ deps.log?.(" 2. 运行: pod install");
852
+ deps.log?.(" 3. 使用 .xcworkspace 打开项目");
853
+ deps.log?.(" 解决方案 2: 手动下载 SVGKit.framework 并添加到项目中");
854
+ deps.log?.(" 解决方案 3: 如果不需要 SVG 支持,可以移除插件中的 SVG 相关代码");
572
855
  }
573
856
  }
857
+ catch (error) {
858
+ }
574
859
  }
575
- if (frameworks && frameworks.length > 0) {
576
- logs.push('注意: 系统库需要手动在 Xcode 中添加到 Link Binary With Libraries:');
577
- for (const framework of frameworks) {
578
- logs.push(` - ${framework}`);
860
+ if (allFrameworks.length > 0 ||
861
+ xcframeworks.length > 0) {
862
+ deps.log?.("步骤 6.7: 更新 FRAMEWORK_SEARCH_PATHS");
863
+ try {
864
+ let content = deps.readFileSync(projectPbxprojPath, "utf8");
865
+ const frameworksSearchPath = '"$(PROJECT_DIR)/Frameworks"';
866
+ let modified = false;
867
+ const frameworkSearchPathsRegex = /(FRAMEWORK_SEARCH_PATHS\s*=\s*\()([\s\S]*?)(\t+\);)/g;
868
+ const matches = [];
869
+ let match;
870
+ while ((match = frameworkSearchPathsRegex.exec(content)) !== null) {
871
+ matches.push({
872
+ full: match[0],
873
+ start: match[1],
874
+ middle: match[2],
875
+ end: match[3],
876
+ index: match.index
877
+ });
878
+ }
879
+ for (let i = matches.length - 1; i >= 0; i--) {
880
+ const m = matches[i];
881
+ const currentPaths = m.middle.trim();
882
+ if (!currentPaths.includes("Frameworks") &&
883
+ !currentPaths.includes(frameworksSearchPath)) {
884
+ const indent = m.end.match(/^\t+/)?.[0] || '\t\t\t\t';
885
+ const newPathEntry = `${indent}${frameworksSearchPath},\n`;
886
+ const newMiddle = currentPaths
887
+ ? `${currentPaths}\n${newPathEntry}`
888
+ : newPathEntry;
889
+ const newContent = `${m.start}${newMiddle}${m.end}`;
890
+ const before = content.substring(0, m.index);
891
+ const after = content.substring(m.index + m.full.length);
892
+ content = before + newContent + after;
893
+ modified = true;
894
+ }
895
+ }
896
+ if (modified) {
897
+ deps.writeFileSync(projectPbxprojPath, content, "utf8");
898
+ deps.log?.(`已添加 Frameworks 目录到所有 FRAMEWORK_SEARCH_PATHS 配置`);
899
+ }
900
+ else {
901
+ deps.log?.(`所有 FRAMEWORK_SEARCH_PATHS 已包含 Frameworks 目录`);
902
+ }
579
903
  }
904
+ catch (error) {
905
+ deps.log?.(`警告: 更新 FRAMEWORK_SEARCH_PATHS 失败: ${error instanceof Error ? error.message : String(error)}`);
906
+ }
907
+ }
908
+ }
909
+ deps.log?.("步骤 7: 清理临时文件");
910
+ try {
911
+ deps.log?.(` 检查临时目录: ${tempDir}`);
912
+ if (deps.existsSync(tempDir)) {
913
+ deps.log?.(` 开始清理临时目录: ${tempDir}`);
914
+ await new Promise((resolve) => {
915
+ const timeout = deps.setTimeout(() => {
916
+ deps.log?.(`警告: 清理临时目录超时: ${tempDir}`);
917
+ resolve();
918
+ }, 5000);
919
+ deps.exec(`rm -rf "${tempDir}"`, (error) => {
920
+ deps.clearTimeout(timeout);
921
+ if (error) {
922
+ deps.log?.(`警告: 清理临时目录失败: ${tempDir} (${error.message})`);
923
+ }
924
+ else {
925
+ deps.log?.(`✓ 已清理临时目录: ${tempDir}`);
926
+ }
927
+ resolve();
928
+ });
929
+ });
930
+ }
931
+ else {
932
+ deps.log?.(` 临时目录不存在,跳过清理: ${tempDir}`);
580
933
  }
934
+ const frameworksDir = deps.join(projectPath, "Frameworks");
935
+ const frameworkTempDir = deps.join(frameworksDir, ".temp_framework_copy");
936
+ deps.log?.(` 检查 framework 临时目录: ${frameworkTempDir}`);
937
+ if (deps.existsSync(frameworkTempDir)) {
938
+ deps.log?.(` 开始清理 framework 临时目录: ${frameworkTempDir}`);
939
+ await new Promise((resolve) => {
940
+ const timeout = deps.setTimeout(() => {
941
+ deps.log?.(`警告: 清理 framework 临时目录超时: ${frameworkTempDir}`);
942
+ resolve();
943
+ }, 5000);
944
+ deps.exec(`rm -rf "${frameworkTempDir}"`, (error) => {
945
+ deps.clearTimeout(timeout);
946
+ if (error) {
947
+ deps.log?.(`警告: 清理 framework 临时目录失败: ${frameworkTempDir} (${error.message})`);
948
+ }
949
+ else {
950
+ deps.log?.(`✓ 已清理 framework 临时目录: ${frameworkTempDir}`);
951
+ }
952
+ resolve();
953
+ });
954
+ });
955
+ }
956
+ else {
957
+ deps.log?.(` framework 临时目录不存在,跳过清理: ${frameworkTempDir}`);
958
+ }
959
+ deps.log?.("✓ 清理临时文件完成");
581
960
  }
961
+ catch (cleanupError) {
962
+ deps.log?.(`警告: 清理临时文件时出错: ${cleanupError instanceof Error
963
+ ? cleanupError.message
964
+ : String(cleanupError)}`);
965
+ }
966
+ deps.log?.("原生插件集成完成");
582
967
  return {
583
968
  success: true,
584
- message: '原生插件集成成功',
585
- logs
969
+ message: "原生插件集成成功",
970
+ logs: [],
586
971
  };
587
972
  }
588
973
  catch (error) {
589
- logs.push(`原生插件集成异常: ${error instanceof Error ? error.message : String(error)}`);
974
+ deps.log?.(`原生插件集成异常: ${error instanceof Error ? error.message : String(error)}`);
975
+ try {
976
+ const tempDir = deps.join(projectPath, ".temp");
977
+ if (deps.existsSync(tempDir)) {
978
+ deps.exec(`rm -rf "${tempDir}"`, () => { });
979
+ }
980
+ const frameworksDir = deps.join(projectPath, "Frameworks");
981
+ const frameworkTempDir = deps.join(frameworksDir, ".temp_framework_copy");
982
+ if (deps.existsSync(frameworkTempDir)) {
983
+ deps.exec(`rm -rf "${frameworkTempDir}"`, () => { });
984
+ }
985
+ }
986
+ catch { }
590
987
  return {
591
988
  success: false,
592
989
  error: `原生插件集成异常: ${error instanceof Error ? error.message : String(error)}`,
593
- logs
990
+ logs: [],
594
991
  };
595
992
  }
596
993
  }