@ttmg/cli 0.3.7 → 0.3.8-beta.2

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 (44) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/package.json +1 -1
  3. package/dist/public/assets/Detail-DS6U5mRS.js +1 -0
  4. package/dist/public/assets/Detail-DS6U5mRS.js.br +0 -0
  5. package/dist/public/assets/{MonetizationMode-gxP1CQqy.js → MonetizationMode-C8WTPdaL.js} +1 -1
  6. package/dist/public/assets/{MonetizationModeSummary-CD54_ROf.js → MonetizationModeSummary-BS7EmGz7.js} +1 -1
  7. package/dist/public/assets/{baseForm-d3x5z6BS.js → baseForm-Dj23Zmdr.js} +1 -1
  8. package/dist/public/assets/baseForm-Dj23Zmdr.js.br +0 -0
  9. package/dist/public/assets/{index-Bz8ZWlHc.js → index-BOpd1gIe.js} +1 -1
  10. package/dist/public/assets/{index-07cXGo3a.js → index-BVIWa0s0.js} +3 -3
  11. package/dist/public/assets/index-BVIWa0s0.js.br +0 -0
  12. package/dist/public/assets/{index-E142v_RY.js → index-BY1PUmxY.js} +1 -1
  13. package/dist/public/assets/index-BY1PUmxY.js.br +0 -0
  14. package/dist/public/assets/{index-CQR5bkkv.js → index-C6Obic7Y.js} +1 -1
  15. package/dist/public/assets/{index-CYD_pNmH.js → index-C6fJhGVf.js} +1 -1
  16. package/dist/public/assets/{index-utYbqRWL.js → index-C898tUMR.js} +1 -1
  17. package/dist/public/assets/index-C898tUMR.js.br +0 -0
  18. package/dist/public/assets/{index-C0Izps-u.js → index-C8Mc6d6E.js} +1 -1
  19. package/dist/public/assets/{index-Cr55HKuS.js → index-CCoPaW9N.js} +1 -1
  20. package/dist/public/assets/{index-766JxwXs.js → index-Ca4ZdkdC.js} +1 -1
  21. package/dist/public/assets/index-Ca4ZdkdC.js.br +0 -0
  22. package/dist/public/assets/{index-Ba-my-vz.js → index-Co_mqsxn.js} +1 -1
  23. package/dist/public/assets/{index-BNtIdKnQ.js → index-DZTvsbCe.js} +1 -1
  24. package/dist/public/assets/{index-B7M-KACw.js → index-D_Y0HD2X.js} +1 -1
  25. package/dist/public/assets/{index-BBHUSsVA.js → index-TXPH6UQv.js} +1 -1
  26. package/dist/public/assets/index-TXPH6UQv.js.br +0 -0
  27. package/dist/public/assets/{index-C4Lcagww.js → index-UZ08kMPF.js} +1 -1
  28. package/dist/public/assets/{index-CLDvvBgM.js → index-oYIBlQRY.js} +1 -1
  29. package/dist/public/assets/{index-BZOItUfZ.js → index-sGtn40-w.js} +1 -1
  30. package/dist/public/assets/index-sGtn40-w.js.br +0 -0
  31. package/dist/public/assets/{times-BvsrZcqF.js → times-_NUvbbyU.js} +1 -1
  32. package/dist/public/index.html +1 -1
  33. package/dist/scripts/docs/capture.js +71 -3
  34. package/dist/scripts/docs/render.js +334 -62
  35. package/package.json +1 -1
  36. package/dist/public/assets/Detail-BzyVtzyL.js +0 -1
  37. package/dist/public/assets/Detail-BzyVtzyL.js.br +0 -0
  38. package/dist/public/assets/baseForm-d3x5z6BS.js.br +0 -0
  39. package/dist/public/assets/index-07cXGo3a.js.br +0 -0
  40. package/dist/public/assets/index-766JxwXs.js.br +0 -0
  41. package/dist/public/assets/index-BBHUSsVA.js.br +0 -0
  42. package/dist/public/assets/index-BZOItUfZ.js.br +0 -0
  43. package/dist/public/assets/index-E142v_RY.js.br +0 -0
  44. package/dist/public/assets/index-utYbqRWL.js.br +0 -0
@@ -134,10 +134,78 @@ async function stabilizePage(Runtime) {
134
134
  });
135
135
  }
136
136
 
137
- async function captureFullPage(Page, Emulation, outputPath, viewport) {
137
+ async function getMeaningfulContentHeight(Runtime, viewport) {
138
+ const result = await Runtime.evaluate({
139
+ expression: `(() => {
140
+ const viewportHeight = window.innerHeight || ${Number(viewport.height) || 900};
141
+ const viewportWidth = window.innerWidth || ${Number(viewport.width) || 1440};
142
+ const meaningfulSelector = [
143
+ 'img',
144
+ 'svg',
145
+ 'canvas',
146
+ 'video',
147
+ 'button',
148
+ 'input',
149
+ 'textarea',
150
+ 'select',
151
+ '[role="button"]'
152
+ ].join(',');
153
+
154
+ const isVisible = element => {
155
+ const style = window.getComputedStyle(element);
156
+ if (
157
+ style.display === 'none' ||
158
+ style.visibility === 'hidden' ||
159
+ style.opacity === '0'
160
+ ) {
161
+ return false;
162
+ }
163
+ const rect = element.getBoundingClientRect();
164
+ return rect.width > 0 && rect.height > 0;
165
+ };
166
+
167
+ let bottom = 0;
168
+ for (const element of Array.from(document.body.querySelectorAll('*'))) {
169
+ if (!isVisible(element)) continue;
170
+ const rect = element.getBoundingClientRect();
171
+ const tag = element.tagName.toLowerCase();
172
+ const hasText = Boolean((element.innerText || '').trim());
173
+ const hasVisibleChild = Array.from(element.children || []).some(child => isVisible(child));
174
+ const hasLeafText = hasText && !hasVisibleChild;
175
+ const hasMeaningfulNode = Boolean(element.matches(meaningfulSelector));
176
+ const isLayoutShell =
177
+ rect.top <= 1 &&
178
+ rect.left <= 1 &&
179
+ rect.width >= viewportWidth * 0.9 &&
180
+ rect.height >= viewportHeight * 0.9;
181
+
182
+ if (isLayoutShell) continue;
183
+
184
+ const isVisualPrimitive = ['svg', 'img', 'canvas', 'video'].includes(tag);
185
+ const isInteractive = ['button', 'input', 'textarea', 'select'].includes(tag) || element.getAttribute('role') === 'button';
186
+ const hasUsefulContent = hasLeafText || hasMeaningfulNode || isVisualPrimitive || isInteractive;
187
+ if (!hasUsefulContent) continue;
188
+
189
+ bottom = Math.max(bottom, Math.ceil(rect.bottom + window.scrollY));
190
+ }
191
+
192
+ return Math.max(0, bottom);
193
+ })()`,
194
+ returnByValue: true,
195
+ awaitPromise: true,
196
+ });
197
+
198
+ return Number(result?.result?.value || 0);
199
+ }
200
+
201
+ async function captureFullPage(Page, Runtime, Emulation, outputPath, viewport) {
138
202
  const metrics = await Page.getLayoutMetrics();
139
203
  const width = Math.max(viewport.width, Math.ceil(metrics.contentSize.width || viewport.width));
140
- const height = Math.max(viewport.height, Math.ceil(metrics.contentSize.height || viewport.height));
204
+ const meaningfulHeight = await getMeaningfulContentHeight(Runtime, viewport);
205
+ const height = Math.max(
206
+ Math.min(viewport.height, 900),
207
+ meaningfulHeight ? meaningfulHeight + 48 : Math.ceil(metrics.contentSize.height || viewport.height),
208
+ );
141
209
  const safeHeight = Math.min(height, 16000);
142
210
 
143
211
  await setViewport(Emulation, width, safeHeight);
@@ -244,7 +312,7 @@ async function main() {
244
312
 
245
313
  const fileName = `${recipe.id}.${locale}.png`;
246
314
  const outputPath = path.join(assetsDir, fileName);
247
- await captureFullPage(Page, Emulation, outputPath, viewport);
315
+ await captureFullPage(Page, Runtime, Emulation, outputPath, viewport);
248
316
  console.log(`[ttmg-docs] captured ${fileName}`);
249
317
  }
250
318
  }
@@ -46,28 +46,25 @@ function buildManifest({ recipes, locales, outputDir, guideTitle, guideSections,
46
46
  };
47
47
  }
48
48
 
49
- function renderLocaleBlock(locale, recipe) {
49
+ function renderRecipeBlock(locale, recipe, headingLevel = 3) {
50
50
  const note = recipe.notes[locale];
51
- const purposeLabel = locale === 'zh-CN' ? '页面说明' : 'What this page is for';
51
+ const purposeLabel = locale === 'zh-CN' ? '用途' : 'Purpose';
52
52
  const screenshotLabel = locale === 'zh-CN' ? '截图' : 'Screenshot';
53
53
  const entryLabel = locale === 'zh-CN' ? '适用场景' : 'When to use';
54
- const stepsLabel = locale === 'zh-CN' ? '操作步骤' : 'How to use it';
55
- const checksLabel = locale === 'zh-CN' ? '建议重点查看' : 'What to check';
56
- const tipsLabel = locale === 'zh-CN' ? '提示' : 'Tip';
54
+ const stepsLabel = locale === 'zh-CN' ? '怎么做' : 'How to use it';
55
+ const checksLabel = locale === 'zh-CN' ? '重点检查' : 'What to check';
57
56
  const imagePath = `./assets/${recipe.id}.${locale}.png`;
58
57
  const punctuation = locale === 'zh-CN' ? ':' : ': ';
58
+ const heading = headingLevel ? '#'.repeat(headingLevel) : '';
59
59
 
60
60
  return [
61
- `## ${note.title}`,
62
- '',
61
+ ...(heading ? [`${heading} ${note.title}`, ''] : []),
63
62
  `- ${purposeLabel}${punctuation}${note.purpose}`,
64
63
  `- ${entryLabel}${punctuation}${note.whenToUse}`,
65
- ...note.highlights.map(item => `- ${item}`),
66
64
  `- ${stepsLabel}${punctuation}`,
67
65
  ...note.steps.map((item, index) => ` ${index + 1}. ${item}`),
68
66
  `- ${checksLabel}${punctuation}`,
69
67
  ...note.keyChecks.map(item => ` - ${item}`),
70
- `- ${tipsLabel}${punctuation}${note.tip}`,
71
68
  `- ${screenshotLabel}${punctuation}`,
72
69
  '',
73
70
  `![${note.title}](${imagePath})`,
@@ -75,35 +72,333 @@ function renderLocaleBlock(locale, recipe) {
75
72
  ].join('\n');
76
73
  }
77
74
 
78
- function renderLocaleSection({ recipes, locale, heading, guideSections = [] }) {
75
+ function getRecipeById(recipes, id) {
76
+ return recipes.find(recipe => recipe.id === id);
77
+ }
78
+
79
+ function renderCommand({ title, description, command }, headingLevel = 3) {
80
+ const heading = '#'.repeat(headingLevel);
79
81
  return [
80
- `# ${heading}`,
82
+ `${heading} ${title}`,
83
+ '',
84
+ description,
81
85
  '',
82
- renderGuideSections(guideSections),
86
+ `\`${command}\``,
83
87
  '',
84
- ...recipes.map(recipe => renderLocaleBlock(locale, recipe)),
85
88
  ].join('\n');
86
89
  }
87
90
 
88
- function renderGuideSections(sections = []) {
89
- return sections
90
- .map(section => [
91
- `## ${section.title}`,
91
+ const zhSectionNumbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
92
+
93
+ function formatSectionTitle(locale, index, title) {
94
+ if (!index) {
95
+ return title;
96
+ }
97
+ if (locale === 'zh-CN') {
98
+ return `${zhSectionNumbers[index - 1] || index}、${title}`;
99
+ }
100
+ return `${index}. ${title}`;
101
+ }
102
+
103
+ function renderGettingStarted(locale, sectionIndex) {
104
+ if (locale === 'zh-CN') {
105
+ return [
106
+ `## ${formatSectionTitle(locale, sectionIndex, '开始之前')}`,
92
107
  '',
93
- ...section.summary.map(item => `- ${item}`),
108
+ renderCommand({
109
+ title: '安装调试工具',
110
+ description: '在小游戏项目目录中安装并使用 `ttmg` CLI。安装完成后,后续调试、登录、配置和上传发布都通过这个工具进入。',
111
+ command: 'npm install -g @ttmg/cli',
112
+ }),
113
+ renderCommand({
114
+ title: '登录开发账号',
115
+ description: '需要读取项目概览、上传发布或使用依赖开发者平台状态的能力时,先登录开发者账号。',
116
+ command: 'ttmg login',
117
+ }),
118
+ renderCommand({
119
+ title: '设置本地语言',
120
+ description: '如果希望 CLI 提示和部分本地输出使用中文,可以设置本地语言;不带值执行时会进入语言选择。',
121
+ command: 'ttmg config set lang zh-CN',
122
+ }),
123
+ renderCommand({
124
+ title: '设置网络代理',
125
+ description: '如果你的办公网络、公司代理或本地环境无法直接访问开发者平台接口,需要先配置代理。已能正常登录、拉取项目概览和上传发布的开发者通常不需要设置。',
126
+ command: 'ttmg config set proxy http://127.0.0.1:7890',
127
+ }),
128
+ '- 查看当前配置:`ttmg config get lang` 或 `ttmg config get proxy`。',
129
+ '- 清除某项配置:`ttmg config delete <key>`。',
94
130
  '',
95
- ...section.commands.map(command => [
96
- `### ${command.title}`,
97
- '',
98
- `- ${command.description}`,
99
- '',
100
- `\`${command.command}\``,
101
- '',
102
- ].join('\n')),
103
- ...section.points.map(item => `- ${item}`),
131
+ ].join('\n');
132
+ }
133
+
134
+ return [
135
+ `## ${formatSectionTitle(locale, sectionIndex, 'Before You Start')}`,
136
+ '',
137
+ renderCommand({
138
+ title: 'Install the Debugging Tool',
139
+ description: 'Install and use the `ttmg` CLI in your mini-game project. Debugging, sign-in, configuration, and upload flows all start from this tool.',
140
+ command: 'npm install -g @ttmg/cli',
141
+ }),
142
+ renderCommand({
143
+ title: 'Sign in with a Developer Account',
144
+ description: 'Sign in before using features that depend on developer-platform state, such as Project overview, Upload & publish, or platform-side capability checks.',
145
+ command: 'ttmg login',
146
+ }),
147
+ renderCommand({
148
+ title: 'Set the Local Language',
149
+ description: 'Set the local CLI language if you want command prompts and local output in English. Running the command without a value opens an interactive language picker.',
150
+ command: 'ttmg config set lang en-US',
151
+ }),
152
+ renderCommand({
153
+ title: 'Set a Network Proxy',
154
+ description: 'Configure a proxy only when your office network, company proxy, or local environment cannot reach developer-platform APIs directly. If sign-in, Project overview, and upload already work, you usually do not need this.',
155
+ command: 'ttmg config set proxy http://127.0.0.1:7890',
156
+ }),
157
+ '- Check current values with `ttmg config get lang` or `ttmg config get proxy`.',
158
+ '- Remove a setting with `ttmg config delete <key>`.',
159
+ '',
160
+ ].join('\n');
161
+ }
162
+
163
+ function renderIntro(locale, sectionIndex) {
164
+ if (locale === 'zh-CN') {
165
+ return [
166
+ `## ${formatSectionTitle(locale, sectionIndex, '导读')}`,
167
+ '',
168
+ '这份文档面向第一次使用 TikTok 小游戏调试工具的开发者,目标是帮助你完成本地连接、项目检查、能力接入和上传发布。',
169
+ '',
170
+ '- 如果你只是想把项目跑起来,先看“开始之前”和“开始调试”。',
171
+ '- 如果你要确认项目配置是否完整,看“项目概览”。',
172
+ '- 如果你要接入登录、分享、广告、内购、直玩卡等平台能力,看“接入助手”。',
173
+ '- 如果你准备提交预览版本,看“上传发布”。',
104
174
  '',
105
- ].join('\n'))
106
- .join('\n');
175
+ ].join('\n');
176
+ }
177
+
178
+ return [
179
+ `## ${formatSectionTitle(locale, sectionIndex, 'Overview')}`,
180
+ '',
181
+ 'This guide is for developers using the TikTok mini-game debugging tool for the first time. It helps you connect locally, check project setup, integrate platform capabilities, and upload preview builds.',
182
+ '',
183
+ '- To get the project running, start with “Before You Start” and “Start Debugging”.',
184
+ '- To verify project setup, read “Project Overview”.',
185
+ '- To integrate login, sharing, ads, IAP, direct-play cards, or other platform capabilities, read “Integration Assistant”.',
186
+ '- To prepare a preview build, read “Upload & Publish”.',
187
+ '',
188
+ ].join('\n');
189
+ }
190
+
191
+ function renderModuleSection({ locale, title, summary, recipes, sectionIndex }) {
192
+ const renderRecipe = recipe => {
193
+ const noteTitle = recipe.notes[locale]?.title;
194
+ return String(noteTitle || '').toLowerCase() === String(title || '').toLowerCase()
195
+ ? renderRecipeBlock(locale, recipe, null)
196
+ : renderRecipeBlock(locale, recipe, 3);
197
+ };
198
+
199
+ return [
200
+ `## ${formatSectionTitle(locale, sectionIndex, title)}`,
201
+ '',
202
+ ...summary.map(item => `- ${item}`),
203
+ '',
204
+ ...recipes.map(renderRecipe),
205
+ ].join('\n');
206
+ }
207
+
208
+ function renderIntegrationAssistantSection({ recipes, locale, sectionIndex }) {
209
+ const overview = getRecipeById(recipes, 'integration-assistant-map');
210
+ const imagePath = overview ? `./assets/${overview.id}.${locale}.png` : '';
211
+ const imageAlt = overview?.notes?.[locale]?.title || (locale === 'zh-CN' ? '接入助手' : 'Integration Assistant');
212
+
213
+ if (locale === 'zh-CN') {
214
+ return [
215
+ `## ${formatSectionTitle(locale, sectionIndex, '接入助手')}`,
216
+ '',
217
+ '### 整体介绍',
218
+ '',
219
+ '- 接入助手用于帮助开发者理解 TikTok 小游戏常见平台能力,并把“要接什么能力”和“为什么要接”先讲清楚。',
220
+ '- 使用时建议先从业务类型出发,再进入具体能力详情页查看前置条件、调试路径和注意事项。',
221
+ '- 如果只是第一次了解工具能力,可以先看本节的变现模式和能力概览,不需要立即进入每个能力详情。',
222
+ '',
223
+ '### 变现模式',
224
+ '',
225
+ '- 接入助手会按小游戏常见变现方式提供能力组合建议,帮助开发者快速判断当前项目优先关注哪些能力。',
226
+ '- `IAA` 适合以广告变现为主的项目,重点关注广告、分享、复访和基础调试能力。',
227
+ '- `IAP` 适合以内购变现为主的项目,重点关注登录态、内购、支付链路验证和上传发布前检查。',
228
+ '- `IAAP` 适合广告与内购同时存在的项目,需要同时关注广告、内购、用户身份、复访和分享链路。',
229
+ '- 每个模式下的能力会用必选、推荐、可选等标签表达优先级,便于开发者按接入阶段逐步完成。',
230
+ '',
231
+ '### 能力概览',
232
+ '',
233
+ '- 能力概览按照身份与授权、商业化变现、增长与复访、分享与裂变、基础能力等方向组织。',
234
+ '- 每个能力卡片会说明能力用途、关联 API 和接入优先级;折叠区域支持点击整张卡片展开。',
235
+ '- 进入能力详情后,可以继续查看前置检查、建议调试路径和注意事项。',
236
+ '- 截图:',
237
+ '',
238
+ imagePath ? `![${imageAlt}](${imagePath})` : '',
239
+ '',
240
+ ].join('\n');
241
+ }
242
+
243
+ return [
244
+ `## ${formatSectionTitle(locale, sectionIndex, 'Integration Assistant')}`,
245
+ '',
246
+ '### Overview',
247
+ '',
248
+ '- Integration Assistant helps developers understand common TikTok mini-game platform capabilities and clarify what to integrate before going into implementation details.',
249
+ '- Start from the business model, then open capability detail pages for prerequisites, debugging paths, and tips.',
250
+ '- If you are exploring the tool for the first time, review monetization modes and the capability overview before opening individual capability details.',
251
+ '',
252
+ '### Monetization Modes',
253
+ '',
254
+ '- Integration Assistant recommends capability combinations by common mini-game monetization models.',
255
+ '- `IAA` is for ad-driven games and focuses on ads, sharing, revisit, and foundational debugging capabilities.',
256
+ '- `IAP` is for in-app-purchase-driven games and focuses on identity, purchase flow validation, and pre-upload checks.',
257
+ '- `IAAP` is for games that use both ads and in-app purchases, so ads, IAP, identity, revisit, and sharing should be considered together.',
258
+ '- Capabilities are marked with priority labels such as required, recommended, and optional so teams can integrate in stages.',
259
+ '',
260
+ '### Capability Overview',
261
+ '',
262
+ '- Capabilities are grouped by identity and authorization, monetization, growth and revisit, sharing, and foundational capabilities.',
263
+ '- Each capability card explains its purpose, related APIs, and priority. Collapsed sections can be expanded by clicking the whole card.',
264
+ '- Open a capability detail page to continue with prerequisites, suggested debugging path, and tips.',
265
+ '- Screenshot:',
266
+ '',
267
+ imagePath ? `![${imageAlt}](${imagePath})` : '',
268
+ '',
269
+ ].join('\n');
270
+ }
271
+
272
+ function renderUploadPublishSection({ recipes, locale, sectionIndex }) {
273
+ const upload = getRecipeById(recipes, 'upload-publish');
274
+ const restricted = getRecipeById(recipes, 'upload-game-restricted');
275
+ const uploadImagePath = upload ? `./assets/${upload.id}.${locale}.png` : '';
276
+ const uploadImageAlt = upload?.notes?.[locale]?.title || (locale === 'zh-CN' ? '上传发布' : 'Upload & Publish');
277
+ const restrictedImagePath = restricted ? `./assets/${restricted.id}.${locale}.png` : '';
278
+ const restrictedImageAlt = restricted?.notes?.[locale]?.title || (locale === 'zh-CN' ? '上传发布权限受限态' : 'Upload & Publish restricted state');
279
+
280
+ if (locale === 'zh-CN') {
281
+ return [
282
+ `## ${formatSectionTitle(locale, sectionIndex, '上传发布')}`,
283
+ '',
284
+ '### 整体介绍',
285
+ '',
286
+ '- 上传发布用于把上传前检查、版本说明、代码上传和预览版本记录串成一个完整流程。',
287
+ '- 使用时建议先看代码预检结果,确认没有阻塞项后再填写版本说明并上传。',
288
+ '- 上传完成后,可以在历史记录里查看预览版本和二维码,方便测试、验收和团队协作。',
289
+ '',
290
+ '### 代码预检',
291
+ '',
292
+ '- 代码预检会在上传前检查包体、配置、API 使用和性能相关风险。',
293
+ '- 如果出现失败项,优先展开详情定位问题;包体大小检查旁会提供详细说明入口,方便查看整包、主包和独立分包限制。',
294
+ '- Unity 项目需要特别关注总包体限制和 Wasm Code Split 相关提示。',
295
+ '',
296
+ '### 代码上传',
297
+ '',
298
+ '- 代码预检没有阻塞项后,填写版本说明并执行上传。',
299
+ '- 版本说明应简要描述本次变更内容,便于测试、产品和其他开发者识别预览版本。',
300
+ '- 如果账号无上传权限,页面会在模块内展示受限原因和下一步处理建议。',
301
+ '',
302
+ '### 历史记录',
303
+ '',
304
+ '- 历史记录用于查看已上传的预览版本、状态和二维码。',
305
+ '- 上传成功后不需要停留在一次性成功态,可以回到历史记录继续分发二维码或复查版本。',
306
+ '- 截图:',
307
+ '',
308
+ uploadImagePath ? `![${uploadImageAlt}](${uploadImagePath})` : '',
309
+ '',
310
+ restrictedImagePath ? `![${restrictedImageAlt}](${restrictedImagePath})` : '',
311
+ '',
312
+ ].join('\n');
313
+ }
314
+
315
+ return [
316
+ `## ${formatSectionTitle(locale, sectionIndex, 'Upload & Publish')}`,
317
+ '',
318
+ '### Overview',
319
+ '',
320
+ '- Upload & Publish combines pre-upload checks, version notes, code upload, and preview-build records into one workflow.',
321
+ '- Review code precheck first, resolve blocking issues, then enter a version note and upload.',
322
+ '- After upload, use history records to find preview builds and QR codes for testing, review, and team collaboration.',
323
+ '',
324
+ '### Code Precheck',
325
+ '',
326
+ '- Code precheck runs before upload and checks package size, configuration, API usage, and performance risks.',
327
+ '- If there are failed items, expand details first. Package size checks include a documentation entry for project, main-package, and independent-package limits.',
328
+ '- Unity projects should pay special attention to total package size and Wasm Code Split warnings.',
329
+ '',
330
+ '### Code Upload',
331
+ '',
332
+ '- After precheck has no blocking issues, enter a version note and upload the code.',
333
+ '- Keep the version note short and clear so QA, PM, and other developers can identify the preview build.',
334
+ '- If the account does not have upload permission, the module shows the reason and next actions in place.',
335
+ '',
336
+ '### History Records',
337
+ '',
338
+ '- History records show uploaded preview builds, status, and QR codes.',
339
+ '- After a successful upload, use history records to distribute QR codes or review previous builds instead of treating upload as a one-time success state.',
340
+ '- Screenshot:',
341
+ '',
342
+ uploadImagePath ? `![${uploadImageAlt}](${uploadImagePath})` : '',
343
+ '',
344
+ restrictedImagePath ? `![${restrictedImageAlt}](${restrictedImagePath})` : '',
345
+ '',
346
+ ].join('\n');
347
+ }
348
+
349
+ function renderSidebarModules({ recipes, locale }) {
350
+ const byId = id => getRecipeById(recipes, id);
351
+ if (locale === 'zh-CN') {
352
+ return [
353
+ renderModuleSection({
354
+ locale,
355
+ title: '开始调试',
356
+ sectionIndex: 3,
357
+ summary: [
358
+ '用于启动本地调试、扫码连接客户端,并在连接前确认启动模式和调试选项。',
359
+ '如果需要复现指定入口、投流参数或分包场景,先配置启动模式,再回到开始调试页扫码。',
360
+ ],
361
+ recipes: [byId('home'), byId('launch-mode')].filter(Boolean),
362
+ }),
363
+ renderModuleSection({
364
+ locale,
365
+ title: '项目概览',
366
+ sectionIndex: 4,
367
+ summary: [
368
+ '用于核对小游戏基础资料、包体信息、信任域名、用户协议和隐私政策。',
369
+ '上传前建议先确认这里的信息没有缺失,避免后续预检或提审时反复排查基础配置。',
370
+ ],
371
+ recipes: [byId('project-detail')].filter(Boolean),
372
+ }),
373
+ renderIntegrationAssistantSection({ recipes, locale, sectionIndex: 5 }),
374
+ renderUploadPublishSection({ recipes, locale, sectionIndex: 6 }),
375
+ ].join('\n');
376
+ }
377
+
378
+ return [
379
+ renderModuleSection({
380
+ locale,
381
+ title: 'Start Debugging',
382
+ sectionIndex: 3,
383
+ summary: [
384
+ 'Use this module to start local debugging, scan with the TikTok client, and verify launch mode and debugging options before connecting.',
385
+ 'If you need to reproduce a specific entry, campaign parameter, or subpackage scenario, configure Launch mode first and then return to scan.',
386
+ ],
387
+ recipes: [byId('home'), byId('launch-mode')].filter(Boolean),
388
+ }),
389
+ renderModuleSection({
390
+ locale,
391
+ title: 'Project Overview',
392
+ sectionIndex: 4,
393
+ summary: [
394
+ 'Use this module to verify project metadata, package size, trusted domains, Terms URL, and Privacy URL.',
395
+ 'Before upload, check this page first so basic configuration issues do not become upload or review blockers later.',
396
+ ],
397
+ recipes: [byId('project-detail')].filter(Boolean),
398
+ }),
399
+ renderIntegrationAssistantSection({ recipes, locale, sectionIndex: 5 }),
400
+ renderUploadPublishSection({ recipes, locale, sectionIndex: 6 }),
401
+ ].join('\n');
107
402
  }
108
403
 
109
404
  function renderFaqSection(title, items = []) {
@@ -120,46 +415,23 @@ function renderFaqSection(title, items = []) {
120
415
  }
121
416
 
122
417
  function renderMarkdown({ recipes, guideTitle, guideSections, guideFaqs = {} }) {
123
- const screenshotCount = recipes.length;
124
- const zhSection = renderLocaleSection({
125
- recipes,
126
- locale: 'zh-CN',
127
- heading: '中文',
128
- guideSections: guideSections['zh-CN'],
129
- });
130
-
131
- const enSection = renderLocaleSection({
132
- recipes,
133
- locale: 'en-US',
134
- heading: 'English',
135
- guideSections: guideSections['en-US'],
136
- });
137
-
138
- const zhFaqSection = renderFaqSection('常见问题', guideFaqs['zh-CN']);
139
- const enFaqSection = renderFaqSection('FAQ', guideFaqs['en-US']);
418
+ const zhFaqSection = renderFaqSection(formatSectionTitle('zh-CN', 7, '常见问题'), guideFaqs['zh-CN']);
419
+ const enFaqSection = renderFaqSection(formatSectionTitle('en-US', 7, 'FAQ'), guideFaqs['en-US']);
140
420
 
141
421
  return [
142
422
  `# ${guideTitle}`,
143
423
  '',
144
- `本指南面向外部开发者,整体分为“通用调试能力说明”和“Unity 调试说明”两部分,并补充 ${screenshotCount} 个关键页面的截图说明。`,
145
- '',
146
- '- 适用对象:第一次接触 TikTok 小游戏调试工具,或需要快速回顾常用操作的开发者。',
147
- '- 结构说明:先看通用调试能力,再按需查看 Unity 调试专项内容。',
148
- '- 阅读方式:建议先看中文,再按需查看英文对照。',
149
- '- 截图仅用于说明页面布局与关键入口,实际文案可能随版本更新有细微差异。',
150
- '',
151
- `This guide is written for external developers and is organized into two parts: general debugging capabilities and Unity debugging guidance, followed by annotated screenshots for ${screenshotCount} key pages.`,
152
- '',
153
- '- Audience: developers who are new to the TikTok mini-game debugging tool or want a quick refresher on the core workflow.',
154
- '- Structure: read the general debugging section first, then move to the Unity-specific section when needed.',
155
- '- Reading tip: start with the Chinese section, then use the English section as needed.',
156
- '- Screenshots are provided to explain layout and entry points; minor wording may change in future versions.',
157
- '',
158
- zhSection,
424
+ renderIntro('zh-CN', 1),
425
+ renderGettingStarted('zh-CN', 2),
426
+ renderSidebarModules({ recipes, locale: 'zh-CN' }),
159
427
  '',
160
428
  zhFaqSection,
161
429
  '',
162
- enSection,
430
+ '# TikTok Mini Game Debugging Tool Guide',
431
+ '',
432
+ renderIntro('en-US', 1),
433
+ renderGettingStarted('en-US', 2),
434
+ renderSidebarModules({ recipes, locale: 'en-US' }),
163
435
  '',
164
436
  enFaqSection,
165
437
  ].join('\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttmg/cli",
3
- "version": "0.3.7",
3
+ "version": "0.3.8-beta.2",
4
4
  "description": "TikTok Mini Game Command Line Tool",
5
5
  "license": "ISC",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- import{d as U,u as ie,c as ve,r as d,i as a,j as e,P as Oe,D as Ke,T as c,H as T,b as C,B as O,e as Re,E as xe,Q as $e,N as _e,J as Fe,a as fe}from"./index-07cXGo3a.js";import{E as Ve}from"./index-CQR5bkkv.js";import{F as k}from"./baseForm-d3x5z6BS.js";import{c as Ge}from"./index-tOg_vZEc.js";import"./times-BvsrZcqF.js";import"./index-BZOItUfZ.js";function qe(s={}){return U({url:"/game/direct-feed-card/list",method:"POST",data:s})}function Ue(s={}){return U({url:"/game/direct-feed-card/scenarios",method:"POST",data:s})}function Qe(s){return U({url:"/game/direct-feed-card/create",method:"POST",data:s})}function Ye(s){return U({url:"/game/direct-feed-card/asset-preview",method:"POST",data:s})}function Be(s={}){return U({url:"/game/assets",method:"POST",data:s})}const He="fyf_promotion_direct_feed_play",je="direct-play-debug",ae="__create_direct_play_card__",se="strength_recovery",Je=2,G=String(Je),ze={cardName:"",cardDesc:"",cardType:G,scenario:se,subPkg:"__GAME__",params:""};function w(s,l){if(typeof s=="string"&&s.trim())return s;if(s&&typeof s=="object"){const r=s;if(r.errorMsg)return r.errorMsg;if(r.StatusMessage)return r.StatusMessage;if(r.message)return r.message}return l}function We(s){return s?s<1024?`${s} B`:s<1024*1024?`${(s/1024).toFixed(1)} KB`:`${(s/1024/1024).toFixed(2)} MB`:"-"}function Xe(s){return s?new Date(s*1e3).toLocaleString():"-"}function Ze(s){return s==="preview"?a("ia.directPlay.stage2.assetGroup.preview"):s==="live"?a("ia.directPlay.stage2.assetGroup.live"):a("ia.directPlay.stage2.assetGroup.review")}function ea(s){return{...s||_e,scene:He}}function aa(s){return s.pkgType==="independent"?s.independentPkg||s.pkgName||a("independentPackage"):a("gameMainPackage")}function te(s){return!s||s==="__GAME__"?a("gameMainPackage"):s}function q(s,l){return s?l?.[s]?l[s]:s==="strength_recovery"?a("ia.directPlay.stage2.create.scenario.strengthRecovery"):s==="recall_scenario"?a("ia.directPlay.stage2.create.scenario.recallScenario"):s:"-"}function ta(s){return s?Number(s.audit_status)===1?a("ia.directPlay.stage2.cardStatus.approved"):Number(s.audit_status)===0||Number(s.status)===0?a("ia.directPlay.stage2.cardStatus.pending"):"":""}function sa(s,l){const r=s?.direct_feed_card||{},u=String(s?.content_id||r.content_id||"").trim();return u?{audit_status:Number(r.audit_status??1),status:Number(r.status??1),content_id:u,card_name:String(r.card_name||l.cardName),card_desc:String(r.card_desc||l.cardDesc),card_type:Number(r.card_type??l.cardType),scenario:String(r.scenario||l.scenario),sub_pkg:String(r.sub_pkg||l.subPkg),params:String(r.params||l.params||""),priority:r.priority===void 0?void 0:Number(r.priority)}:null}function J(){return[{value:se,label:q(se)}]}const ia=()=>{const s=ie(),{state:{selectedLaunchOption:l,gameDetail:r,launchOptions:u,packages:S},setLaunchOptions:I,setSelectedLaunchOption:i}=ve(),[x,Q]=d.useState([]),[N,D]=d.useState([]),[_,K]=d.useState("select"),[f,Y]=d.useState(""),[M,re]=d.useState(""),[ne,B]=d.useState(""),[ce,de]=d.useState(""),[le,R]=d.useState(""),[oe,z]=d.useState(""),[ue,W]=d.useState(""),[Pe,ge]=d.useState(!0),[Ne,pe]=d.useState(!1),[be,me]=d.useState(!1),[he,X]=d.useState(G),[A,ye]=d.useState(J),b=d.useRef(null),Z=d.useMemo(()=>ea(l),[l]),h=d.useMemo(()=>({appId:r?.app_id,clientKey:r?.client_key,miniGameId:r?.app_id}),[r?.app_id,r?.client_key]),E=d.useMemo(()=>x.find(t=>t.content_id===f)||null,[x,f]),L=d.useMemo(()=>N.find(t=>t.asset_id===M)||null,[N,M]),$=d.useMemo(()=>A.reduce((t,n)=>(n?.value&&(t[n.value]=n.label&&n.label!==n.value?n.label:q(n.value)),t),{}),[A]),H=d.useMemo(()=>{const t=A.filter(o=>o.cardType===void 0||Number(o.cardType)===Number(he));return(t.length>0?t:J()).map(o=>({...o,label:q(o.value,$)}))},[he,$,A]),Te=d.useMemo(()=>N.map(t=>({label:`${t.file_name||t.asset_id} · v${t.version||"-"}`,value:t.asset_id})),[N]),Ce=d.useMemo(()=>[{label:a("ia.directPlay.stage2.create.option"),value:ae},...x.map(t=>({label:`${t.card_name} · ${q(t.scenario,$)} · ${te(t.sub_pkg)}`,value:t.content_id}))],[x,$]),Se=d.useMemo(()=>[{label:a("ia.directPlay.stage2.create.cardType.fixed"),value:"1"},{label:a("ia.directPlay.stage2.create.cardType.dynamic"),value:"2"}],[]),Ie=d.useMemo(()=>{const t=new Set(["__GAME__"]);return(S||[]).forEach(n=>{n?.type==="independent"&&n.name&&t.add(n.name)}),u.forEach(n=>{n.pkgType==="independent"&&n.independentPkg&&t.add(n.independentPkg)}),Array.from(t).map(n=>({label:te(n),value:n}))},[u,S]),Ee=d.useMemo(()=>e.jsxs("span",{className:"integration-assistant-direct-play-label-with-info",children:[e.jsx("span",{children:a("ia.directPlay.stage2.create.cardType")}),e.jsx(Oe,{position:"top",trigger:"hover",showArrow:!0,content:e.jsxs("div",{className:"integration-assistant-direct-play-info-popover",children:[e.jsx(c.Text,{children:a("ia.directPlay.stage2.create.cardType.dynamicDesc")}),e.jsx(c.Text,{children:a("ia.directPlay.stage2.create.cardType.fixedDesc")})]}),children:e.jsx("span",{className:"integration-assistant-direct-play-info-icon","aria-label":"card type info",children:e.jsx(Ke,{})})})]}),[]),ke=d.useCallback(t=>{const n=String(t||G);X(n);const o=A.filter(g=>g.cardType===void 0||Number(g.cardType)===Number(n)),y=o.length>0?o:J(),m=y[0]?.value,j=b.current?.getValue?.("scenario"),P=y.some(g=>g.value===j);b.current?.setValue?.("cardType",n),m&&!P&&b.current?.setValue?.("scenario",m)},[A]),F=d.useCallback(async t=>{ge(!0),de("");try{const[n,o,y]=await Promise.allSettled([qe({appId:h.appId,clientKey:h.clientKey}),Be({appId:h.appId,miniGameId:h.miniGameId,clientKey:h.clientKey}),Ue({appId:h.appId,clientKey:h.clientKey})]),m=n.status==="fulfilled"?n.value:null,j=o.status==="fulfilled"?o.value:null,P=y.status==="fulfilled"?y.value:null;if(n.status==="rejected"||m?.error||m?.code!==0||!m?.data)throw new Error(w(m?.error,a("ia.directPlay.stage2.loadCardsFailed")));if(o.status==="rejected"||j?.error||j?.code!==0||!j?.data)throw new Error(w(j?.error,a("ia.directPlay.stage2.loadAssetsFailed")));const g=m.data.cards||[],V=(j.data.preview_assets||[]).map(p=>({...p,group:"preview"}));Q(g),D(V),P?.code===0&&P.data?.scenarios?.length?ye(P.data.scenarios):ye(p=>p.length>0?p:J()),Y(p=>{if(t?.contentId&&g.some(v=>v.content_id===t.contentId))return t.contentId;if(t?.cardName){const v=g.find(ee=>ee.card_name===t.cardName);if(v?.content_id)return v.content_id}return p&&g.some(v=>v.content_id===p)?p:g[0]?.content_id||""}),re(p=>p&&V.some(v=>v.asset_id===p)?p:V[0]?.asset_id||"")}catch(n){de(w(n,a("ia.directPlay.stage2.loadResourcesFailed")))}finally{ge(!1)}},[h.appId,h.clientKey,h.miniGameId]);d.useEffect(()=>{F()},[F]),d.useEffect(()=>{const t=H[0]?.value;if(!t)return;const n=b.current?.getValue?.("scenario");H.some(y=>y.value===n)||b.current?.setValue?.("scenario",t)},[H]);const we=d.useCallback(()=>{const t={...Z,id:je,name:a("ia.directPlay.stage1.generatedModeName")},n=u.filter(m=>m.id!==je),o=n.findIndex(m=>m.id==="created"),y=o>=0?[...n.slice(0,o),t,...n.slice(o)]:[...n,t];I(y),i(t),s("/")},[u,s,I,i,Z]),De=d.useCallback(async()=>{try{const t=await b.current?.validate(),n=String(t?.cardName||"").trim(),o=String(t?.cardDesc||"").trim(),y=String(t?.scenario||"").trim(),m=String(t?.subPkg||"__GAME__").trim()||"__GAME__",j=String(t?.params||"").trim(),P=Number(t?.cardType||0);if(!n||!o||!y||!P)return;me(!0),z(""),W("");const g=await Qe({appId:h.appId,clientKey:h.clientKey,directFeedCard:{cardName:n,cardDesc:o,cardType:P,scenario:y,subPkg:m,params:j||void 0}});if(g?.error||g?.code!==0)throw new Error(w(g?.error,a("ia.directPlay.stage2.create.failed")));const V=String(g?.data?.content_id||g?.data?.direct_feed_card?.content_id||""),p=sa(g?.data,{cardName:n,cardDesc:o,cardType:P,scenario:y,subPkg:m,params:j});await F({contentId:V,cardName:n}),p&&(Q(v=>{const ee=v.filter(Le=>Le.content_id!==p.content_id);return[p,...ee]}),Y(p.content_id)),K("select"),W(a("ia.directPlay.stage2.create.success")),R(""),B(""),b.current?.reset?.(),X(G)}catch(t){if(t?.name==="ValidateError")return;z(w(t,a("ia.directPlay.stage2.create.failed")))}finally{me(!1)}},[F,h.appId,h.clientKey]),Me=d.useCallback(t=>{if(t===ae){K("create"),Y(""),R(""),B("");return}K("select"),Y(t||"")},[]),Ae=d.useCallback(async()=>{if(!f||!M){R(a("ia.directPlay.stage2.selectRequired"));return}pe(!0),R("");try{const t=await Ye({assetId:M,contentId:f});if(t?.error||t?.code!==0||!t?.data?.preview_url)throw new Error(w(t?.error,a("ia.directPlay.stage2.previewFailed")));B(t.data.preview_url)}catch(t){B(""),R(w(t,a("ia.directPlay.stage2.previewFailed")))}finally{pe(!1)}},[M,f]);return e.jsxs("div",{className:"integration-assistant-direct-play-grid",children:[e.jsxs(T,{className:"integration-assistant-direct-play-card",bordered:!0,children:[e.jsx("div",{className:"integration-assistant-section-head",children:e.jsxs("div",{children:[e.jsx(c.Title,{heading:5,children:a("ia.directPlay.stage1.title")}),e.jsx(c.Paragraph,{className:"integration-assistant-section-desc",children:a("ia.directPlay.stage1.desc")})]})}),e.jsxs("div",{className:"integration-assistant-direct-play-summary",children:[e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage1.modeName")}),e.jsx(c.Text,{children:a("ia.directPlay.stage1.modeValue")})]}),e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage1.scene")}),e.jsx(c.Text,{children:a("scene_fyf_promotion_direct_feed_play")})]}),e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage1.package")}),e.jsx(c.Text,{children:aa(Z)})]})]}),e.jsx("div",{className:"integration-assistant-actions",children:e.jsx(C,{theme:"solid",onClick:we,children:a("ia.directPlay.stage1.createQr")})})]}),e.jsxs(T,{className:"integration-assistant-direct-play-card",bordered:!0,children:[e.jsx(O,{className:"integration-assistant-direct-play-banner integration-assistant-direct-play-banner-top",fullMode:!1,bordered:!1,closeIcon:null,type:"info",description:a("ia.directPlay.stage2.banner")}),e.jsx("div",{className:"integration-assistant-section-head",children:e.jsxs("div",{className:"integration-assistant-direct-play-stage-head",children:[e.jsx(c.Title,{heading:5,children:a("ia.directPlay.stage2.title")}),e.jsx(c.Paragraph,{className:"integration-assistant-section-desc",children:a("ia.directPlay.stage2.desc")})]})}),e.jsx(O,{className:"integration-assistant-direct-play-banner integration-assistant-direct-play-banner-inline",fullMode:!1,bordered:!1,closeIcon:null,type:"warning",description:a("ia.directPlay.versionNotice")}),ce?e.jsx(O,{className:"integration-assistant-direct-play-banner",fullMode:!1,bordered:!1,closeIcon:null,type:"danger",description:ce}):null,le?e.jsx(O,{className:"integration-assistant-direct-play-banner",fullMode:!1,bordered:!1,closeIcon:null,type:"danger",description:le}):null,oe?e.jsx(O,{className:"integration-assistant-direct-play-banner",fullMode:!1,bordered:!1,closeIcon:null,type:"danger",description:oe}):null,ue?e.jsx(O,{className:"integration-assistant-direct-play-banner",fullMode:!1,bordered:!1,closeIcon:null,type:"success",description:ue}):null,Pe?e.jsx("div",{className:"integration-assistant-direct-play-loading",children:e.jsx(Re,{size:"large"})}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"integration-assistant-direct-play-form",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"integration-assistant-direct-play-field-head",children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage2.cardSelect")}),e.jsx(C,{theme:"borderless",onClick:()=>F(),children:a("ia.directPlay.stage2.refresh")})]}),e.jsx(xe,{className:"integration-assistant-direct-play-select",value:_==="create"?ae:f||void 0,optionList:Ce,onChange:t=>Me(t),placeholder:a("ia.directPlay.stage2.cardSelect")})]}),_==="select"?e.jsxs("div",{children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage2.assetSelect")}),e.jsx(xe,{className:"integration-assistant-direct-play-select",value:M||void 0,optionList:Te,onChange:t=>re(t),placeholder:a("ia.directPlay.stage2.assetSelect")})]}):null]}),_==="create"?e.jsx("div",{className:"integration-assistant-direct-play-create-wrap",children:e.jsxs("div",{className:"integration-assistant-direct-play-panel",children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage2.create.title")}),e.jsx(c.Paragraph,{className:"integration-assistant-section-desc",children:a("ia.directPlay.stage2.create.desc")}),e.jsx(k,{className:"integration-assistant-direct-play-create-form",initValues:ze,getFormApi:t=>{b.current=t},onValueChange:t=>{if(z(""),W(""),t&&typeof t=="object"&&"cardType"in t){const n=String(t.cardType||G);X(n)}},children:e.jsxs("div",{className:"integration-assistant-direct-play-create-grid",children:[e.jsx(k.Input,{field:"cardName",label:a("ia.directPlay.stage2.create.cardName"),placeholder:a("ia.directPlay.stage2.create.cardNamePlaceholder"),rules:[{required:!0,message:a("notEmpty")}]}),e.jsx(k.Select,{field:"cardType",label:Ee,optionList:Se,onChange:ke,rules:[{required:!0,message:a("notEmpty")}]}),e.jsx(k.Input,{field:"cardDesc",label:a("ia.directPlay.stage2.create.cardDesc"),placeholder:a("ia.directPlay.stage2.create.cardDescPlaceholder"),rules:[{required:!0,message:a("notEmpty")}]}),e.jsx(k.Select,{field:"subPkg",label:a("ia.directPlay.stage2.create.subPkg"),optionList:Ie,rules:[{required:!0,message:a("notEmpty")}]}),e.jsx(k.Select,{field:"scenario",label:a("ia.directPlay.stage2.create.scenario"),optionList:H,rules:[{required:!0,message:a("notEmpty")}]}),e.jsx(k.Input,{field:"params",label:a("ia.directPlay.stage2.create.params"),placeholder:a("ia.directPlay.stage2.create.paramsPlaceholder")})]})}),e.jsx("div",{className:"integration-assistant-actions",children:e.jsx(C,{theme:"solid",type:"primary",loading:be,onClick:De,children:a("ia.directPlay.stage2.create.submit")})})]})}):null,_==="select"?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"integration-assistant-direct-play-details",children:[e.jsxs("div",{className:"integration-assistant-direct-play-panel",children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage2.selectedCard")}),E?e.jsxs("ul",{className:"integration-assistant-detail-list",children:[e.jsx("li",{children:`${a("ia.directPlay.stage2.cardName")}${E.card_name}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.cardDesc")}${E.card_desc||"-"}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.cardScenario")}${q(E.scenario,$)}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.cardStatus")}${ta(E)||"-"}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.cardPackage")}${te(E.sub_pkg)}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.cardQueries")}${E.params||"-"}`})]}):e.jsx(c.Paragraph,{className:"integration-assistant-section-desc",children:a("ia.directPlay.stage2.emptyCard")})]}),e.jsxs("div",{className:"integration-assistant-direct-play-panel",children:[e.jsx(c.Text,{strong:!0,children:a("ia.directPlay.stage2.selectedAsset")}),L?e.jsxs("ul",{className:"integration-assistant-detail-list",children:[e.jsx("li",{children:`${a("ia.directPlay.stage2.assetGroup")}${Ze(L.group)}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.assetFile")}${L.file_name||"-"}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.assetVersion")}${L.version||"-"}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.assetSize")}${We(L.file_size)}`}),e.jsx("li",{children:`${a("ia.directPlay.stage2.assetUploaded")}${Xe(L.uploaded_at)}`})]}):e.jsx(c.Paragraph,{className:"integration-assistant-section-desc",children:a("ia.directPlay.stage2.emptyAsset")})]})]}),e.jsx("div",{className:"integration-assistant-actions",children:e.jsx(C,{theme:"solid",loading:Ne,onClick:Ae,children:a("ia.directPlay.stage2.generate")})})]}):null,_==="select"&&ne?e.jsxs("div",{className:"integration-assistant-direct-play-preview",children:[e.jsx("div",{className:"integration-assistant-direct-play-qr",children:e.jsx($e,{value:ne,size:180})}),e.jsx("div",{className:"integration-assistant-direct-play-preview-content",children:e.jsx(c.Text,{className:"integration-assistant-section-desc",children:a("ia.directPlay.stage2.qrDesc")})})]}):null]})]})]})},ra={sidebar_revisit:{modeId:"sidebar-revisit-debug",scene:"center",sceneKey:"scene_center",titleKey:"ia.revisit.sidebar.panel.title",descKey:"ia.revisit.sidebar.panel.desc",modeValueKey:"ia.revisit.sidebar.panel.modeValue",generatedModeNameKey:"ia.revisit.sidebar.panel.generatedModeName",signalValueKey:"ia.revisit.sidebar.panel.signalValue",createQrKey:"ia.revisit.sidebar.panel.createQr"},shortcut_revisit:{modeId:"shortcut-revisit-debug",scene:"desktop_shortcut",sceneKey:"scene_shortcut",titleKey:"ia.revisit.shortcut.panel.title",descKey:"ia.revisit.shortcut.panel.desc",modeValueKey:"ia.revisit.shortcut.panel.modeValue",generatedModeNameKey:"ia.revisit.shortcut.panel.generatedModeName",signalValueKey:"ia.revisit.shortcut.panel.signalValue",createQrKey:"ia.revisit.shortcut.panel.createQr"}};function na(s,l){return{...s||_e,scene:l}}function ca(s){return s.pkgType==="independent"?s.independentPkg||s.pkgName||a("independentPackage"):a("gameMainPackage")}const da=({capabilityKey:s})=>{const l=ie(),{state:{selectedLaunchOption:r,launchOptions:u},setLaunchOptions:S,setSelectedLaunchOption:I}=ve(),i=ra[s],x=d.useMemo(()=>na(r,i.scene),[i.scene,r]),Q=d.useCallback(()=>{const N={...x,id:i.modeId,name:a(i.generatedModeNameKey)},D=u.filter(f=>f.id!==i.modeId),_=D.findIndex(f=>f.id==="created"),K=_>=0?[...D.slice(0,_),N,...D.slice(_)]:[...D,N];S(K),I(N),l("/")},[i.generatedModeNameKey,i.modeId,u,l,x,S,I]);return e.jsx("div",{className:"integration-assistant-direct-play-grid",children:e.jsxs(T,{className:"integration-assistant-direct-play-card",bordered:!0,children:[e.jsx("div",{className:"integration-assistant-section-head",children:e.jsxs("div",{children:[e.jsx(c.Title,{heading:5,children:a(i.titleKey)}),e.jsx(c.Paragraph,{className:"integration-assistant-section-desc",children:a(i.descKey)})]})}),e.jsxs("div",{className:"integration-assistant-direct-play-summary",children:[e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.revisit.panel.modeName")}),e.jsx(c.Text,{children:a(i.modeValueKey)})]}),e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.revisit.panel.scene")}),e.jsx(c.Text,{children:a(i.sceneKey)})]}),e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.revisit.panel.launchParams")}),e.jsx(c.Text,{children:`scene=${i.scene}`})]}),e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.revisit.panel.package")}),e.jsx(c.Text,{children:ca(x)})]}),e.jsxs("div",{className:"integration-assistant-direct-play-row",children:[e.jsx(c.Text,{strong:!0,children:a("ia.revisit.panel.signal")}),e.jsx(c.Text,{children:a(i.signalValueKey)})]})]}),e.jsx("div",{className:"integration-assistant-actions",children:e.jsx(C,{theme:"solid",onClick:Q,children:a(i.createQrKey)})})]})})},ha=()=>{const s=ie(),{capabilityKey:l}=Fe(),r=l?Ge[l]:void 0,u=i=>a(i),S=r?.actions.filter(i=>i.labelKey==="ia.action.openCapabilityDoc")||[],I=i=>{if(i.type==="external"&&i.href){window.open(i.href,i.target||"_blank","noopener,noreferrer");return}i.type==="route"&&i.path&&s(i.path)};return!r||r.hidden?e.jsx("div",{className:"integration-assistant-page integration-assistant-detail-page",children:e.jsxs(T,{bordered:!0,children:[e.jsx(Ve,{description:a("ia.detail.notFound")}),e.jsx("div",{className:"integration-assistant-detail-backalone",children:e.jsx(C,{onClick:()=>s("/integration_assistant"),children:a("ia.detail.backToMap")})})]})}):e.jsxs("div",{className:"integration-assistant-page integration-assistant-detail-page",children:[e.jsx("div",{className:"integration-assistant-detail-backalone",children:e.jsx(C,{theme:"borderless",onClick:()=>s("/integration_assistant"),children:a("ia.detail.backToMap")})}),e.jsx(T,{className:"integration-assistant-detail-hero",bordered:!1,children:e.jsxs("div",{className:"integration-assistant-detail-hero-content",children:[e.jsxs("div",{className:"integration-assistant-detail-title-row",children:[e.jsx("div",{className:"integration-assistant-map-icon","aria-hidden":"true",children:r.icon}),e.jsxs("div",{children:[e.jsx(c.Title,{heading:3,className:"integration-assistant-title",children:u(r.titleKey)}),e.jsx(c.Paragraph,{className:"integration-assistant-subtitle",children:u(r.summaryKey)})]})]}),e.jsxs("div",{className:"integration-assistant-map-meta",children:[r.sceneKey&&e.jsx(fe,{color:"blue",children:`${a("ia.sceneLabel")}${u(r.sceneKey)}`}),r.apiTags.map(i=>e.jsx("span",{children:e.jsx(fe,{children:i})},i))]}),e.jsx("div",{className:"integration-assistant-actions",children:S.map(i=>e.jsx(C,{theme:i.theme||"light",onClick:()=>I(i),children:u(i.labelKey)},`${i.type}:${i.path||i.href||i.labelKey}`))})]})}),e.jsxs("div",{className:"integration-assistant-detail-grid",children:[e.jsxs(T,{className:"integration-assistant-detail-card",bordered:!0,children:[e.jsx(c.Title,{heading:5,children:a("ia.section.prerequisites")}),e.jsx("div",{className:"integration-assistant-detail-info-list",children:r.prerequisiteKeys.map(i=>e.jsxs("div",{className:"integration-assistant-detail-info-item",children:[e.jsx("span",{className:"integration-assistant-detail-info-marker"}),e.jsx(c.Text,{className:"integration-assistant-detail-info-text",children:u(i)})]},i))})]}),e.jsxs(T,{className:"integration-assistant-detail-card",bordered:!0,children:[e.jsx(c.Title,{heading:5,children:a("ia.section.steps")}),e.jsx("div",{className:"integration-assistant-detail-step-list",children:r.stepKeys.map((i,x)=>e.jsxs("div",{className:"integration-assistant-detail-step",children:[e.jsx("span",{className:"integration-assistant-detail-step-index",children:x+1}),e.jsx(c.Text,{className:"integration-assistant-detail-step-text",children:u(i)})]},i))})]}),e.jsxs(T,{className:"integration-assistant-detail-card",bordered:!0,children:[e.jsx(c.Title,{heading:5,children:a("ia.section.tips")}),e.jsx("div",{className:"integration-assistant-detail-info-list",children:r.tipKeys.map(i=>e.jsxs("div",{className:"integration-assistant-detail-info-item",children:[e.jsx("span",{className:"integration-assistant-detail-info-marker"}),e.jsx(c.Text,{className:"integration-assistant-detail-info-text",children:u(i)})]},i))})]})]}),r.key==="direct_play_card"?e.jsx(ia,{}):null,r.key==="sidebar_revisit"||r.key==="shortcut_revisit"?e.jsx(da,{capabilityKey:r.key}):null]})};export{ha as IntegrationAssistantDetail};