siluzan-tso-cli 1.1.60-beta.2 → 1.1.60-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +882 -253
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/core/agent-conventions.md +10 -0
- package/dist/skill/references/core/playbooks.md +12 -11
- package/dist/skill/references/core/workflows.md +1 -1
- package/dist/skill/references/report-templates/README.md +2 -0
- package/dist/skill/references/report-templates/bing-period-report.md +2 -0
- package/dist/skill/references/report-templates/google-ads-diagnosis.md +2 -0
- package/dist/skill/references/report-templates/google-inquiry-analysis.md +11 -0
- package/dist/skill/references/report-templates/google-period-report-excel.md +2 -0
- package/dist/skill/references/report-templates/google-period-report.md +4 -1
- package/dist/skill/references/report-templates/google-quarterly-report.md +2 -0
- package/dist/skill/references/report-templates/market-analysis-report.md +2 -0
- package/dist/skill/references/report-templates/meta-account-diagnosis-report.md +2 -0
- package/dist/skill/references/report-templates/meta-period-report.md +2 -0
- package/dist/skill/references/report-templates/okki-weekly-google-client.md +21 -0
- package/dist/skill/references/report-templates/tiktok-period-report.md +2 -0
- package/dist/skill/references/report-templates/website-diagnosis-report.md +2 -0
- package/dist/skill/references/report-templates/yandex-period-report.md +2 -0
- package/dist/skill/report-templates/README.md +2 -0
- package/dist/skill/report-templates/bing-period-report.html +16 -3
- package/dist/skill/report-templates/bing-period-report.md +2 -0
- package/dist/skill/report-templates/google-ads-diagnosis.md +2 -0
- package/dist/skill/report-templates/google-inquiry-analysis.md +11 -0
- package/dist/skill/report-templates/google-period-report-excel.md +2 -0
- package/dist/skill/report-templates/google-period-report.html +35 -6
- package/dist/skill/report-templates/google-period-report.md +4 -1
- package/dist/skill/report-templates/google-quarterly-report.html +1 -1
- package/dist/skill/report-templates/google-quarterly-report.md +2 -0
- package/dist/skill/report-templates/market-analysis-report.md +2 -0
- package/dist/skill/report-templates/meta-account-diagnosis-report.md +2 -0
- package/dist/skill/report-templates/meta-period-report.md +2 -0
- package/dist/skill/report-templates/okki-weekly-google-client.md +21 -0
- package/dist/skill/report-templates/tiktok-period-report.html +4 -2
- package/dist/skill/report-templates/tiktok-period-report.md +2 -0
- package/dist/skill/report-templates/website-diagnosis-report.md +2 -0
- package/dist/skill/report-templates/yandex-period-report.html +4 -2
- package/dist/skill/report-templates/yandex-period-report.md +2 -0
- package/dist/skill/scripts/install.ps1 +1 -1
- package/dist/skill/scripts/install.sh +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5212,6 +5212,63 @@ var init_media_account_batch = __esm({
|
|
|
5212
5212
|
}
|
|
5213
5213
|
});
|
|
5214
5214
|
|
|
5215
|
+
// src/report-i18n/lang.ts
|
|
5216
|
+
function resolveReportLang(opts) {
|
|
5217
|
+
const flag = opts.flag?.trim();
|
|
5218
|
+
if (flag) return parseLang(flag, "--lang");
|
|
5219
|
+
if (opts.meta && typeof opts.meta === "object" && !Array.isArray(opts.meta)) {
|
|
5220
|
+
const raw = opts.meta.lang;
|
|
5221
|
+
if (raw == null || raw === "") return "zh";
|
|
5222
|
+
return parseLang(String(raw), "meta.lang");
|
|
5223
|
+
}
|
|
5224
|
+
return "zh";
|
|
5225
|
+
}
|
|
5226
|
+
function htmlLangAttr(lang) {
|
|
5227
|
+
return lang === "en" ? "en" : "zh-CN";
|
|
5228
|
+
}
|
|
5229
|
+
function stampMetaLang(payload, lang) {
|
|
5230
|
+
const prev = payload.meta;
|
|
5231
|
+
const meta = prev && typeof prev === "object" && !Array.isArray(prev) ? { ...prev, lang } : { lang };
|
|
5232
|
+
return { ...payload, meta };
|
|
5233
|
+
}
|
|
5234
|
+
function readReportLangOrExit(opts) {
|
|
5235
|
+
try {
|
|
5236
|
+
return resolveReportLang(opts);
|
|
5237
|
+
} catch (err) {
|
|
5238
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
5239
|
+
console.error(`
|
|
5240
|
+
\u274C ${message}
|
|
5241
|
+
`);
|
|
5242
|
+
process.exit(1);
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5245
|
+
function assertHtmlLangMatches(html, lang) {
|
|
5246
|
+
const match = html.match(/<html\b[^>]*\blang\s*=\s*["']([^"']+)["']/i);
|
|
5247
|
+
const found = (match?.[1] ?? "").trim().toLowerCase();
|
|
5248
|
+
const ok = lang === "en" ? found === "en" || found.startsWith("en-") : found === "zh" || found.startsWith("zh-");
|
|
5249
|
+
if (!ok) {
|
|
5250
|
+
throw new ReportLangError(
|
|
5251
|
+
`html lang="${found || "(missing)"}" \u4E0E\u7EC8\u7A3F\u8BED\u8A00 ${lang} \u4E0D\u4E00\u81F4\uFF08\u4E2D\u6587\u5199 zh-CN\uFF0C\u82F1\u6587\u5199 en\uFF09`
|
|
5252
|
+
);
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
function parseLang(raw, source) {
|
|
5256
|
+
if (raw === "zh" || raw === "en") return raw;
|
|
5257
|
+
throw new ReportLangError(`${source} \u53EA\u63A5\u53D7 zh \u6216 en\uFF0C\u6536\u5230 ${raw}`);
|
|
5258
|
+
}
|
|
5259
|
+
var ReportLangError;
|
|
5260
|
+
var init_lang = __esm({
|
|
5261
|
+
"src/report-i18n/lang.ts"() {
|
|
5262
|
+
"use strict";
|
|
5263
|
+
ReportLangError = class extends Error {
|
|
5264
|
+
constructor(message) {
|
|
5265
|
+
super(message);
|
|
5266
|
+
this.name = "ReportLangError";
|
|
5267
|
+
}
|
|
5268
|
+
};
|
|
5269
|
+
}
|
|
5270
|
+
});
|
|
5271
|
+
|
|
5215
5272
|
// src/commands/accounts-digest/list-fetch.ts
|
|
5216
5273
|
async function fetchAccountsByMedia(media, config, opts) {
|
|
5217
5274
|
const cfg = DIGEST_PLATFORM_CONFIG[media];
|
|
@@ -5317,11 +5374,12 @@ function escapeMdCell(s) {
|
|
|
5317
5374
|
function accountLabel(row) {
|
|
5318
5375
|
return row.advertiserName || row.name || "-";
|
|
5319
5376
|
}
|
|
5320
|
-
function buildHitTable(rows, maxCpa) {
|
|
5321
|
-
const
|
|
5377
|
+
function buildHitTable(rows, maxCpa, lang = "zh") {
|
|
5378
|
+
const en = lang === "en";
|
|
5379
|
+
const header = en ? "| Account | Account ID | Spend | Conversions | CPA | Currency | Reason |\n| --- | --- | ---: | ---: | ---: | --- | --- |" : "| \u8D26\u6237\u540D\u79F0 | \u8D26\u6237ID | \u533A\u95F4\u6D88\u8017 | \u8F6C\u5316\u6B21\u6570 | \u8F6C\u5316\u6210\u672C | \u5E01\u79CD | \u547D\u4E2D\u539F\u56E0 |\n| --- | --- | ---: | ---: | ---: | --- | --- |";
|
|
5322
5380
|
const lines = rows.map((r) => {
|
|
5323
|
-
const reason = classifyDigestHit(r, maxCpa) === "zeroConversions" ? "\u96F6\u8F6C\u5316\u4E14\u6D88\u8017\u5DF2\u8D85\u9608\u503C" : "CPA\u9AD8\u4E8E\u9608\u503C";
|
|
5324
|
-
const conv = r.conversions == null ? "\u8F6C\u5316\u672A\u8FD4\u56DE" : String(r.conversions);
|
|
5381
|
+
const reason = classifyDigestHit(r, maxCpa) === "zeroConversions" ? en ? "Zero conversions and spend over the threshold" : "\u96F6\u8F6C\u5316\u4E14\u6D88\u8017\u5DF2\u8D85\u9608\u503C" : en ? "CPA above the threshold" : "CPA\u9AD8\u4E8E\u9608\u503C";
|
|
5382
|
+
const conv = r.conversions == null ? en ? "Conversions missing" : "\u8F6C\u5316\u672A\u8FD4\u56DE" : String(r.conversions);
|
|
5325
5383
|
const cpa = r.cpa == null ? "\u2014" : String(r.cpa);
|
|
5326
5384
|
const spend = r.spend == null ? "\u2014" : String(r.spend);
|
|
5327
5385
|
return `| ${escapeMdCell(accountLabel(r))} | ${r.mediaCustomerId} | ${spend} | ${conv} | ${cpa} | ${r.currencyCode ?? "\u2014"} | ${reason} |`;
|
|
@@ -5330,6 +5388,7 @@ function buildHitTable(rows, maxCpa) {
|
|
|
5330
5388
|
}
|
|
5331
5389
|
function buildDigestAgentBrief(opts) {
|
|
5332
5390
|
const { rows, scanned, validAccountCount, spendPositiveCount, maxCpa, zeroConversions } = opts;
|
|
5391
|
+
const en = opts.lang === "en";
|
|
5333
5392
|
let highCpa = 0;
|
|
5334
5393
|
let zeroConvHits = 0;
|
|
5335
5394
|
for (const r of rows) {
|
|
@@ -5343,11 +5402,11 @@ function buildDigestAgentBrief(opts) {
|
|
|
5343
5402
|
const allClear = patrol && rows.length === 0;
|
|
5344
5403
|
let userDelivery;
|
|
5345
5404
|
if (allClear && maxCpa != null) {
|
|
5346
|
-
userDelivery = `\u4ECA\u65E5\u6240\u6709\u8D26\u6237\u8F6C\u5316\u6210\u672C\u6B63\u5E38\uFF0C\u5747\u4F4E\u4E8E${maxCpa}\uFF08\u5404\u8D26\u6237\u6309\u81EA\u8EAB currencyCode \u6BD4\u8F83\uFF0C\u52FF\u8DE8\u5E01\u79CD\u5F53\u540C\u4E00\u5355\u4F4D\uFF09`;
|
|
5405
|
+
userDelivery = en ? `Every account's CPA is under ${maxCpa} today (compare each account in its own currencyCode)` : `\u4ECA\u65E5\u6240\u6709\u8D26\u6237\u8F6C\u5316\u6210\u672C\u6B63\u5E38\uFF0C\u5747\u4F4E\u4E8E${maxCpa}\uFF08\u5404\u8D26\u6237\u6309\u81EA\u8EAB currencyCode \u6BD4\u8F83\uFF0C\u52FF\u8DE8\u5E01\u79CD\u5F53\u540C\u4E00\u5355\u4F4D\uFF09`;
|
|
5347
5406
|
} else if (allClear && zeroConversions) {
|
|
5348
|
-
userDelivery = "\u533A\u95F4\u5185\u6CA1\u6709\u6D88\u8017>0\u4E14\u96F6\u8F6C\u5316\uFF08\u6216\u8F6C\u5316\u672A\u8FD4\u56DE\uFF09\u7684\u8D26\u6237";
|
|
5407
|
+
userDelivery = en ? "No account in this range has spend above 0 and zero conversions (or missing conversions)" : "\u533A\u95F4\u5185\u6CA1\u6709\u6D88\u8017>0\u4E14\u96F6\u8F6C\u5316\uFF08\u6216\u8F6C\u5316\u672A\u8FD4\u56DE\uFF09\u7684\u8D26\u6237";
|
|
5349
5408
|
} else if (patrol && rows.length > 0) {
|
|
5350
|
-
userDelivery = buildHitTable(rows, maxCpa);
|
|
5409
|
+
userDelivery = buildHitTable(rows, maxCpa, opts.lang ?? "zh");
|
|
5351
5410
|
} else {
|
|
5352
5411
|
userDelivery = "\u672A\u5F00 --max-cpa / --zero-conversions\u3002\u6309 data.items \u51FA\u8868\uFF1Bmeta.totals \u53EA\u5408\u8BA1 returned \u884C\uFF0C\u7981\u6B62\u5199\u6210\u5168\u90E8\u8D26\u6237\u3002";
|
|
5353
5412
|
}
|
|
@@ -6114,7 +6173,8 @@ async function runAccountsDigest(opts) {
|
|
|
6114
6173
|
validAccountCount: validIds.length,
|
|
6115
6174
|
spendPositiveCount,
|
|
6116
6175
|
maxCpa: opts.maxCpa,
|
|
6117
|
-
zeroConversions: !!opts.zeroConversions
|
|
6176
|
+
zeroConversions: !!opts.zeroConversions,
|
|
6177
|
+
lang: readReportLangOrExit({ flag: opts.lang })
|
|
6118
6178
|
});
|
|
6119
6179
|
const digestPayload = { ok: true, data: { items: rows }, meta, agentBrief };
|
|
6120
6180
|
if (await emitCliJsonOrSnapshot(opts, {
|
|
@@ -6201,6 +6261,7 @@ var init_run = __esm({
|
|
|
6201
6261
|
init_list_fetch();
|
|
6202
6262
|
init_login_customer_id();
|
|
6203
6263
|
init_brief();
|
|
6264
|
+
init_lang();
|
|
6204
6265
|
init_campaign_types();
|
|
6205
6266
|
init_shared();
|
|
6206
6267
|
init_enabled_campaigns();
|
|
@@ -6248,7 +6309,7 @@ function register10(program2) {
|
|
|
6248
6309
|
"--json-out <path>",
|
|
6249
6310
|
"\u843D\u76D8\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\u8DEF\u5F84\uFF09\u5E76\u66F4\u65B0 cli-manifest[-<\u67E5\u8BE2id>].json\uFF1B\u76EE\u5F55\u6A21\u5F0F\u6587\u4EF6\u540D\u4E3A `<section>[-<\u67E5\u8BE2id>].json`\uFF1Bstdout \u4E00\u884C\u6458\u8981 JSON\uFF0C\u542B outlineFile\uFF08TS \u5F0F\u7C7B\u578B\u5728 `*.outline.txt`\uFF09",
|
|
6250
6311
|
void 0
|
|
6251
|
-
).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission \u540E\u518D\u8BF7\u6C42", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
6312
|
+
).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission \u540E\u518D\u8BF7\u6C42", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).option("--lang <lang>", "\u4EA4\u7ED9\u7528\u6237\u7684\u53E5\u5B50\u8BED\u8A00\uFF1Azh \u6216 en\uFF0C\u9ED8\u8BA4 zh").action(
|
|
6252
6313
|
async (opts) => {
|
|
6253
6314
|
await runAccountsDigest({
|
|
6254
6315
|
token: opts.token,
|
|
@@ -6269,7 +6330,8 @@ function register10(program2) {
|
|
|
6269
6330
|
withCampaignTypes: opts.withCampaignTypes,
|
|
6270
6331
|
campaignTypeConcurrency: opts.campaignTypeConcurrency,
|
|
6271
6332
|
withEnabledCampaigns: opts.withEnabledCampaigns,
|
|
6272
|
-
enabledCampaignConcurrency: opts.enabledCampaignConcurrency
|
|
6333
|
+
enabledCampaignConcurrency: opts.enabledCampaignConcurrency,
|
|
6334
|
+
lang: opts.lang
|
|
6273
6335
|
});
|
|
6274
6336
|
}
|
|
6275
6337
|
);
|
|
@@ -7229,6 +7291,372 @@ var init_xlsx_style_engine = __esm({
|
|
|
7229
7291
|
}
|
|
7230
7292
|
});
|
|
7231
7293
|
|
|
7294
|
+
// src/report-i18n/labels.ts
|
|
7295
|
+
function kpiLabels(lang) {
|
|
7296
|
+
return { lang, ...lang === "en" ? EN : ZH };
|
|
7297
|
+
}
|
|
7298
|
+
var ZH, EN;
|
|
7299
|
+
var init_labels = __esm({
|
|
7300
|
+
"src/report-i18n/labels.ts"() {
|
|
7301
|
+
"use strict";
|
|
7302
|
+
ZH = {
|
|
7303
|
+
cost: "\u6D88\u8017",
|
|
7304
|
+
impressions: "\u5C55\u793A\u6B21\u6570",
|
|
7305
|
+
clicks: "\u70B9\u51FB\u6B21\u6570",
|
|
7306
|
+
conversions: "\u8F6C\u5316\u6B21\u6570",
|
|
7307
|
+
ctr: "\u70B9\u51FB\u7387 CTR",
|
|
7308
|
+
cpc: "\u5E73\u5747\u70B9\u51FB\u8D39\u7528",
|
|
7309
|
+
cpa: "\u6BCF\u6B21\u8F6C\u5316\u8D39\u7528 CPA",
|
|
7310
|
+
analysis: "\u5206\u6790",
|
|
7311
|
+
suggestion: "\u5EFA\u8BAE",
|
|
7312
|
+
account: "\u8D26\u6237",
|
|
7313
|
+
currency: "\u8D27\u5E01",
|
|
7314
|
+
mom: "\u73AF\u6BD4"
|
|
7315
|
+
};
|
|
7316
|
+
EN = {
|
|
7317
|
+
cost: "Spend",
|
|
7318
|
+
impressions: "Impressions",
|
|
7319
|
+
clicks: "Clicks",
|
|
7320
|
+
conversions: "Conversions",
|
|
7321
|
+
ctr: "CTR",
|
|
7322
|
+
cpc: "Avg. CPC",
|
|
7323
|
+
cpa: "CPA",
|
|
7324
|
+
analysis: "Analysis",
|
|
7325
|
+
suggestion: "Recommendation",
|
|
7326
|
+
account: "Account",
|
|
7327
|
+
currency: "Currency",
|
|
7328
|
+
mom: "vs prior"
|
|
7329
|
+
};
|
|
7330
|
+
}
|
|
7331
|
+
});
|
|
7332
|
+
|
|
7333
|
+
// src/report-i18n/phrases.en.ts
|
|
7334
|
+
var ENGLISH_PHRASES;
|
|
7335
|
+
var init_phrases_en = __esm({
|
|
7336
|
+
"src/report-i18n/phrases.en.ts"() {
|
|
7337
|
+
"use strict";
|
|
7338
|
+
ENGLISH_PHRASES = {
|
|
7339
|
+
"Google Ads \u5468\u671F\u5206\u6790\u62A5\u544A": "Google Ads period report",
|
|
7340
|
+
"Google Ads \u8D26\u6237\u8BCA\u65AD\u62A5\u544A": "Google Ads account diagnosis",
|
|
7341
|
+
"Google \u5B63\u5EA6\u7ECF\u8425\u62A5\u544A": "Google quarterly business report",
|
|
7342
|
+
"Google \u6708\u5EA6\u7ECF\u8425\u62A5\u544A": "Google monthly business report",
|
|
7343
|
+
"Google \u7ECF\u8425\u62A5\u544A": "Google business report",
|
|
7344
|
+
"Bing \u5E7F\u544A\u8D26\u6237\u5206\u6790\u62A5\u544A": "Bing Ads account report",
|
|
7345
|
+
"Yandex Ads \u8D26\u6237\u5206\u6790\u62A5\u544A": "Yandex Ads account report",
|
|
7346
|
+
"TikTok \u5E7F\u544A\u4E3B\u8D26\u6237\u5206\u6790\u62A5\u544A": "TikTok Ads account report",
|
|
7347
|
+
"Meta / Facebook \u5468\u671F\u5206\u6790\u62A5\u544A": "Meta / Facebook period report",
|
|
7348
|
+
"Meta\uFF08Facebook\uFF09\u8D26\u6237\u8BCA\u65AD\u62A5\u544A": "Meta (Facebook) account diagnosis",
|
|
7349
|
+
"\u7F51\u7AD9\u8BCA\u65AD\u62A5\u544A": "Website diagnosis report",
|
|
7350
|
+
"\u5DE6\u53F3\u6ED1\u52A8\u67E5\u770B\u8868\u683C": "Swipe sideways to see the table",
|
|
7351
|
+
"\u5DE6\u53F3\u6ED1\u52A8\u67E5\u770B\u5176\u4F59\u5217": "Swipe sideways to see more columns",
|
|
7352
|
+
"\u7EDF\u8BA1\u533A\u95F4\u672A\u63D0\u4F9B": "Date range not provided",
|
|
7353
|
+
"\u672A\u627E\u5230\u62A5\u544A\u6570\u636E": "Report data was not found",
|
|
7354
|
+
"\u672A\u6CE8\u5165\u62A5\u544A\u6570\u636E\uFF0C\u8BF7\u901A\u8FC7 facebook-analysis render \u751F\u6210\u3002": "Report data was not injected. Generate this file with facebook-analysis render.",
|
|
7355
|
+
"\uFF08\u5F85 Agent \u64B0\u5199\u6267\u884C\u6458\u8981\uFF09": "(Executive summary not written yet)",
|
|
7356
|
+
"\uFF08\u5F85 Agent \u64B0\u5199\u4F18\u5316\u5EFA\u8BAE\uFF09": "(Recommendations not written yet)",
|
|
7357
|
+
"\uFF08\u5F85 Agent \u64B0\u5199\u884C\u52A8\u9879\uFF09": "(Action items not written yet)",
|
|
7358
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1A\u672C\u8282\u6682\u65E0\u5206\u6790": "Unavailable: no analysis for this section",
|
|
7359
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Adaily-metrics \u672A\u62C9\u53D6\u6216\u533A\u95F4\u5185\u65E0\u6570\u636E": "Unavailable: daily-metrics was not pulled or the range is empty",
|
|
7360
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Adimension-summary \u672A\u62C9\u53D6": "Unavailable: dimension-summary was not pulled",
|
|
7361
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Acampaigns \u672A\u62C9\u53D6": "Unavailable: campaigns was not pulled",
|
|
7362
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Adevices \u672A\u62C9\u53D6": "Unavailable: devices was not pulled",
|
|
7363
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Ageographic \u672A\u62C9\u53D6": "Unavailable: geographic was not pulled",
|
|
7364
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Akeywords \u672A\u62C9\u53D6": "Unavailable: keywords was not pulled",
|
|
7365
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Anegative-keywords \u672A\u62C9\u53D6": "Unavailable: negative-keywords was not pulled",
|
|
7366
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Aaudience \u672A\u62C9\u53D6\u6216\u672C\u671F\u95F4\u65E0\u53D7\u4F17\u884C": "Unavailable: audience was not pulled or this period has no audience rows",
|
|
7367
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Acreative \u672A\u62C9\u53D6": "Unavailable: creative was not pulled",
|
|
7368
|
+
"\u6570\u636E\u4E0D\u53EF\u7528\uFF1Amaterial \u672A\u62C9\u53D6\uFF08\u6807\u51C6\u8D26\u6237\u65E0 Dynamic Creative \u65F6\u5C5E\u6B63\u5E38\uFF09": "Unavailable: material was not pulled (normal when a standard account has no Dynamic Creative)",
|
|
7369
|
+
"\u5F53\u524D\u8D26\u6237\u5426\u8BCD 0 \u6761": "This account has 0 negative keywords",
|
|
7370
|
+
"\u672A\u8FBE\u5230\u8BE5\u9879\u9EC4\u91D1\u8D26\u6237\u6807\u51C6": "Does not meet this Gold Account criterion",
|
|
7371
|
+
"\u5DF2\u8FBE\u6807\uFF0C\u7EE7\u7EED\u4FDD\u6301": "Met \u2014 keep it up",
|
|
7372
|
+
"\u81EA\u9002\u5E94\u641C\u7D22\u5E7F\u544A": "Responsive search ads",
|
|
7373
|
+
"\u81EA\u9002\u5E94\u5C55\u793A\u5E7F\u544A": "Responsive display ads",
|
|
7374
|
+
"\u8F6C\u5316\u8FFD\u8E2A\u8BBE\u7F6E": "Conversion tracking",
|
|
7375
|
+
"G A\u4E0E\u5E7F\u544A\u8D26\u6237\u8054\u7ED3": "GA linked to the ads account",
|
|
7376
|
+
"\u9644\u52A0\u7ED3\u6784\u5316\u4FE1\u606F\u6458\u8981": "Structured snippets",
|
|
7377
|
+
"\u9644\u52A0\u94FE\u63A5": "Sitelinks",
|
|
7378
|
+
"\u9644\u52A0\u5BA3\u4F20\u4FE1\u606F": "Callouts",
|
|
7379
|
+
"\u9644\u52A0\u7535\u8BDD\u4FE1\u606F": "Call extensions",
|
|
7380
|
+
"\u53D7\u4F17\u7FA4\u4F53\u8BBE\u7F6E": "Audiences",
|
|
7381
|
+
"\u51FA\u4EF7\u7B56\u7565": "Bidding strategy",
|
|
7382
|
+
"\u8D26\u6237\u57FA\u672C\u4FE1\u606F\u4E0E\u76EE\u6807\u8BBE\u5B9A": "Account basics and goals",
|
|
7383
|
+
"\u8D26\u6237\u8BCA\u65AD\u6982\u89C8": "Diagnosis overview",
|
|
7384
|
+
"\u6838\u5FC3\u4E1A\u7EE9\u6307\u6807\u5FEB\u7167": "KPI snapshot",
|
|
7385
|
+
"\u8D26\u6237\u5065\u5EB7\u5EA6\u4E0E\u7ED3\u6784\u5206\u6790": "Account health and structure",
|
|
7386
|
+
"\u6295\u653E\u9884\u7B97\u4E0E\u7ADE\u4E89\u529B\u5206\u6790": "Budget and competitiveness",
|
|
7387
|
+
"\u76EE\u6807\u53D7\u4F17\u4E0E\u6295\u653E\u7B56\u7565": "Audience and targeting",
|
|
7388
|
+
"\u7740\u9646\u9875\u5206\u6790": "Landing pages",
|
|
7389
|
+
"\u5173\u952E\u8BCD\u4E0E\u641C\u7D22\u8BCD\u6D1E\u5BDF": "Keywords and search terms",
|
|
7390
|
+
"\u9884\u7B97\u4E0E\u51FA\u4EF7\u7B56\u7565": "Budget and bidding",
|
|
7391
|
+
"\u5E7F\u544A\u521B\u610F\u4E0E\u7D20\u6750\u4F18\u5316": "Ads and assets",
|
|
7392
|
+
"\u65B0\u4EA7\u54C1\u5E94\u7528": "New products",
|
|
7393
|
+
"\u8BCA\u65AD\u603B\u7ED3": "Diagnosis summary",
|
|
7394
|
+
"\u8BCA\u65AD\u9879": "Diagnosis sections",
|
|
7395
|
+
"\u8BCA\u65AD\u5468\u671F": "Diagnosis period",
|
|
7396
|
+
"\u6267\u884C\u6458\u8981": "Executive summary",
|
|
7397
|
+
"\u6267\u884C\u6458\u8981\uFF08\u603B\u89C8\uFF09": "Executive summary",
|
|
7398
|
+
"\u6BCF\u65E5\u6295\u653E\u8D8B\u52BF": "Daily trend",
|
|
7399
|
+
"\u5468\u671F\u6C47\u603B": "Period totals",
|
|
7400
|
+
"\u5E7F\u544A\u7CFB\u5217\u8868\u73B0": "Campaign performance",
|
|
7401
|
+
"\u8BBE\u5907\u5206\u5E03": "Devices",
|
|
7402
|
+
"\u5730\u57DF\u5206\u5E03\uFF08Top 20\uFF09": "Locations (top 20)",
|
|
7403
|
+
"\u5730\u57DF\u5206\u5E03": "Locations",
|
|
7404
|
+
"\u53D7\u4F17\u5206\u5E03\uFF08Top 20\uFF09": "Audiences (top 20)",
|
|
7405
|
+
"\u53D7\u4F17\u5206\u5E03": "Audiences",
|
|
7406
|
+
"\u5173\u952E\u8BCD\u8868\u73B0\uFF08Top 50\uFF09": "Keywords (top 50)",
|
|
7407
|
+
"\u4F18\u5316\u5EFA\u8BAE": "Recommendations",
|
|
7408
|
+
"\u672C\u671F\u6D88\u8017/\u5C55\u793A/\u70B9\u51FB/\u8F6C\u5316/CTR/CPC/CPA \u6982\u89C8": "Spend, impressions, clicks, conversions, CTR, CPC, and CPA",
|
|
7409
|
+
"\u6309\u65E5\u6D88\u8017 / \u8F6C\u5316 / CPA \u66F2\u7EBF": "Daily spend, conversions, and CPA",
|
|
7410
|
+
"\u5168\u5468\u671F\u7D2F\u8BA1\u6838\u5FC3\u6307\u6807\u4E0E\u641C\u7D22\u66DD\u5149\u4EFD\u989D": "Period totals and search impression share",
|
|
7411
|
+
"\u6309\u6D88\u8017\u6392\u5E8F\uFF0C\u542B\u72B6\u6001\u4E0E\u9884\u7B97/\u51FA\u4EF7\u7C7B\u578B": "Sorted by spend, with status and budget or bid type",
|
|
7412
|
+
"PC / \u79FB\u52A8 / \u5E73\u677F \u6D88\u8017\u4E0E\u6548\u679C\u5360\u6BD4": "Spend and results by computer, mobile, and tablet",
|
|
7413
|
+
"\u6309\u6D88\u8017\u6392\u5E8F\u7684\u56FD\u5BB6/\u5730\u533A\u8868\u73B0": "Countries and regions by spend",
|
|
7414
|
+
"\u8DE8\u7CFB\u5217\u5408\u5E76\u5C55\u793A\uFF0C\u6309\u6D88\u8017\u6392\u5E8F": "Combined across campaigns, sorted by spend",
|
|
7415
|
+
"\u7EFC\u5408\u4EE5\u4E0A\u6570\u636E\u7684\u53EF\u6267\u884C\u6539\u8FDB\u5EFA\u8BAE": "Actions based on the data above",
|
|
7416
|
+
"\u5F53\u524D\u8D26\u6237\u5DF2\u6709\u5426\u5B9A\u5173\u952E\u8BCD\uFF08\u7CFB\u5217 / \u5E7F\u544A\u7EC4 / \u8D26\u6237\uFF09\uFF0C\u4E0D\u662F\u672C\u5468\u671F\u6D88\u8017": "Negative keywords already on the account (campaign, ad group, or account), not this period's spend",
|
|
7417
|
+
"AdGroupAudienceData\uFF1A\u610F\u5411/\u5174\u8DA3/\u518D\u8425\u9500/\u5BA2\u6237\u5339\u914D\u7B49\u5217\u8868\u8868\u73B0\uFF0C\u4E0D\u662F\u5E74\u9F84\xD7\u6027\u522B": "Ad group audiences (in-market, affinity, remarketing, customer match), not age or gender",
|
|
7418
|
+
"\u641C\u7D22\u5E7F\u544A\u66DD\u5149\u4EFD\u989D": "Search impression share",
|
|
7419
|
+
"\u5C55\u793A\u6B21\u6570": "Impressions",
|
|
7420
|
+
"\u70B9\u51FB\u6B21\u6570": "Clicks",
|
|
7421
|
+
"\u8F6C\u5316\u6B21\u6570": "Conversions",
|
|
7422
|
+
"\u70B9\u51FB\u7387 CTR": "CTR",
|
|
7423
|
+
"\u5E73\u5747\u70B9\u51FB\u8D39\u7528": "Avg. CPC",
|
|
7424
|
+
"\u6BCF\u6B21\u8F6C\u5316\u8D39\u7528 CPA": "CPA",
|
|
7425
|
+
"\u6BCF\u6B21\u8F6C\u5316\u8D39\u7528": "Cost / conv.",
|
|
7426
|
+
"\u6D3B\u8DC3\u5929\u6570": "Active days",
|
|
7427
|
+
"\u65E5\u5747\u6D88\u8017": "Avg. daily spend",
|
|
7428
|
+
"\u5E7F\u544A\u7CFB\u5217": "Campaign",
|
|
7429
|
+
"\u5E7F\u544A\u7EC4": "Ad group",
|
|
7430
|
+
"\u5173\u952E\u8BCD": "Keyword",
|
|
7431
|
+
"\u5339\u914D\u65B9\u5F0F": "Match type",
|
|
7432
|
+
"\u56FD\u5BB6/\u5730\u533A": "Country / region",
|
|
7433
|
+
"\u641C\u7D22\u8BCD": "Search term",
|
|
7434
|
+
"\u5426\u8BCD": "Negative keywords",
|
|
7435
|
+
"\u5426\u5B9A\u8BCD": "Negative keyword",
|
|
7436
|
+
"\u7EA7\u522B": "Level",
|
|
7437
|
+
"\u53D7\u4F17": "Audience",
|
|
7438
|
+
"\u8BBE\u5907": "Device",
|
|
7439
|
+
"\u72B6\u6001": "Status",
|
|
7440
|
+
"\u7C7B\u578B": "Type",
|
|
7441
|
+
"\u5206\u6790": "Analysis",
|
|
7442
|
+
"\u5EFA\u8BAE": "Recommendation",
|
|
7443
|
+
"\u73AF\u6BD4": "vs prior",
|
|
7444
|
+
"\u8D26\u6237": "Account",
|
|
7445
|
+
"\u8D27\u5E01": "Currency",
|
|
7446
|
+
"\u6D88\u8017": "Spend",
|
|
7447
|
+
"\u5C55\u793A": "Impr.",
|
|
7448
|
+
"\u70B9\u51FB": "Clicks",
|
|
7449
|
+
"\u8F6C\u5316": "Conv.",
|
|
7450
|
+
"\u82B1\u8D39": "Spend",
|
|
7451
|
+
"\u6D88\u8D39": "Spend",
|
|
7452
|
+
"\u9884\u7B97": "Budget",
|
|
7453
|
+
"\u4F59\u989D": "Balance",
|
|
7454
|
+
"\u5B63\u5EA6": "Quarter",
|
|
7455
|
+
"\u6708\u5EA6": "Month",
|
|
7456
|
+
"\u5468\u671F": "Period",
|
|
7457
|
+
"\u672C\u671F": "This period",
|
|
7458
|
+
"\u4E0A\u671F": "Prior period",
|
|
7459
|
+
"\u4E0B\u671F": "Next period",
|
|
7460
|
+
"\u672C\u8282\u6682\u65E0\u6570\u636E": "No data in this section",
|
|
7461
|
+
"\u6682\u65E0\u6570\u636E": "No data",
|
|
7462
|
+
"\u672A\u63D0\u4F9B": "Not provided",
|
|
7463
|
+
"\u672A\u586B\u5199": "Not filled in",
|
|
7464
|
+
"\u672A\u547D\u540D": "Unnamed",
|
|
7465
|
+
"\u672A\u8BBE\u7F6E": "Not set",
|
|
7466
|
+
"\u672A\u542F\u7528": "Off",
|
|
7467
|
+
"\u5DF2\u542F\u7528": "On",
|
|
7468
|
+
"\u5DF2\u6682\u505C": "Paused",
|
|
7469
|
+
"\u5DF2\u79FB\u9664": "Removed",
|
|
7470
|
+
"\u6295\u653E\u4E2D": "Active",
|
|
7471
|
+
"\u672A\u77E5": "Unknown",
|
|
7472
|
+
"\u826F\u597D": "Good",
|
|
7473
|
+
"\u4F18\u79C0": "Excellent",
|
|
7474
|
+
"\u8FBE\u6807": "Met",
|
|
7475
|
+
"\u4E0D\u8FBE\u6807": "Not met",
|
|
7476
|
+
"\u5F85\u4F18\u5316": "Needs work",
|
|
7477
|
+
"\u6570\u636E\u6765\u6E90": "Source",
|
|
7478
|
+
"\u8D26\u6237\u540D\u79F0": "Account name",
|
|
7479
|
+
"\u8D26\u6237\u62A5\u544A": "Account report",
|
|
7480
|
+
"\u8D26\u6237\u603B\u89C8": "Account overview",
|
|
7481
|
+
"\u8D26\u6237\u7ED3\u6784": "Account structure",
|
|
7482
|
+
"\u5E7F\u544A\u7CFB\u5217\u62A5\u544A": "Campaign report",
|
|
7483
|
+
"\u641C\u7D22\u5173\u952E\u5B57\u62A5\u544A": "Keyword report",
|
|
7484
|
+
"\u641C\u7D22\u5B57\u8BCD\u62A5\u544A": "Search terms report",
|
|
7485
|
+
"\u8BBE\u5907\u62A5\u544A": "Device report",
|
|
7486
|
+
"\u5730\u7406\u4F4D\u7F6E\u62A5\u544A": "Geographic report",
|
|
7487
|
+
"\u5E73\u5747\u6BCF\u6B21\u70B9\u51FB\u8D39\u7528": "Avg. CPC",
|
|
7488
|
+
"\u6240\u6709\u8F6C\u5316\u6B21\u6570": "All conversions",
|
|
7489
|
+
"\u8F6C\u5316\u7387": "Conv. rate",
|
|
7490
|
+
"\u5339\u914D\u7C7B\u578B": "Match type",
|
|
7491
|
+
"\u5DF2\u6DFB\u52A0/\u5DF2\u6392\u9664": "Added / excluded",
|
|
7492
|
+
"\u51FA\u4EF7\u8C03\u6574": "Bid adjustment",
|
|
7493
|
+
"\u4E92\u52A8\u6B21\u6570": "Interactions",
|
|
7494
|
+
"\u4E92\u52A8\u7387": "Interaction rate",
|
|
7495
|
+
"\u5730\u7406\u4F4D\u7F6E": "Location",
|
|
7496
|
+
"\u641C\u7D22\u5B57\u8BCD": "Search term",
|
|
7497
|
+
"\u5173\u952E\u5B57": "Keyword",
|
|
7498
|
+
"\u603B\u8BA1": "Total",
|
|
7499
|
+
"\u8986\u76D6\u4EBA\u6570": "Reach",
|
|
7500
|
+
"\u9891\u6B21": "Frequency",
|
|
7501
|
+
"\u5F52\u56E0\u8BBE\u7F6E": "Attribution",
|
|
7502
|
+
"\u6210\u6548\u7C7B\u578B": "Result type",
|
|
7503
|
+
"\u5355\u6B21\u6210\u6548\u8D39\u7528": "Cost per result",
|
|
7504
|
+
"\u5DF2\u82B1\u8D39\u91D1\u989D": "Amount spent",
|
|
7505
|
+
"\u6C47\u603B\u6570\u636E": "Summary",
|
|
7506
|
+
"\u65E5\u8D8B\u52BF": "Daily trend",
|
|
7507
|
+
"\u56FD\u5BB6": "Country",
|
|
7508
|
+
"\u65B9\u6848\u603B\u89C8": "Plan overview",
|
|
7509
|
+
"1-\u5BA2\u6237\u753B\u50CF": "1-Customer profile",
|
|
7510
|
+
"2-\u8D26\u6237\u7ED3\u6784": "2-Account structure",
|
|
7511
|
+
"3-\u8868\u5355\u8BE2\u76D8C1": "3-Lead form C1",
|
|
7512
|
+
"\u5BA2\u6237\u753B\u50CF": "Customer profile",
|
|
7513
|
+
"\u5BA2\u6237\u540D\u79F0": "Customer",
|
|
7514
|
+
"Facebook \u4E3B\u9875": "Facebook page",
|
|
7515
|
+
"\u5B98\u65B9\u7F51\u7AD9": "Website",
|
|
7516
|
+
"\u4E3B\u8425\u4E1A\u52A1": "Business",
|
|
7517
|
+
"\u6838\u5FC3\u4EA7\u54C1": "Products",
|
|
7518
|
+
"\u6838\u5FC3\u5356\u70B9": "Selling points",
|
|
7519
|
+
"\u76EE\u6807\u5E02\u573A": "Target market",
|
|
7520
|
+
"\u8425\u9500\u76EE\u6807": "Goal",
|
|
7521
|
+
"\u65E5\u9884\u7B97": "Daily budget",
|
|
7522
|
+
"\u5E7F\u544A\u7ED3\u6784": "Ad structure",
|
|
7523
|
+
"\u6295\u653E\u7B56\u7565": "Strategy",
|
|
7524
|
+
"\u5E7F\u544A\u8D26\u6237\u7ED3\u6784": "Ad account structure",
|
|
7525
|
+
"\u5F85 pages \u540E\u8865": "Fill in after pages load",
|
|
7526
|
+
"\u8868\u5355\u8BE2\u76D8\uFF08Lead Form\uFF09": "Lead form",
|
|
7527
|
+
"\u8868\u5355\u8BE2\u76D8": "Lead form",
|
|
7528
|
+
"\u8BCA\u65AD\u65F6\u95F4": "Diagnosed at",
|
|
7529
|
+
"\u7F51\u7AD9\u5185\u5BB9\u53CA\u7ED3\u6784": "Site content and structure",
|
|
7530
|
+
"\u8425\u9500\u57FA\u7840\u4E0E\u5E7F\u544A\u843D\u5730\u9875\u8BCA\u65AD": "Marketing basics and landing pages",
|
|
7531
|
+
"\u7528\u6237\u4F53\u9A8C\u4E0E\u8F6C\u5316\u5206\u6790\u8BCA\u65AD": "UX and conversion",
|
|
7532
|
+
"\u7F51\u7AD9\u6027\u80FD\u8BCA\u65AD": "Site performance",
|
|
7533
|
+
"\u4F18\u52BF": "Strengths",
|
|
7534
|
+
"\u4E0D\u8DB3": "Gaps",
|
|
7535
|
+
"\u4F18\u5148\u7EA7": "Priority",
|
|
7536
|
+
"\u5173\u952E\u884C\u52A8": "Actions",
|
|
7537
|
+
"\u9884\u671F\u6548\u679C": "Expected outcome",
|
|
7538
|
+
"\u4F18\u5316\u91CD\u70B9": "Focus",
|
|
7539
|
+
"\u67D0\u67D0\u67D0\u6709\u9650\u516C\u53F8": "Sample Company Ltd.",
|
|
7540
|
+
"\u8BE2\u76D8/\u8F6C\u5316": "Leads / conversions",
|
|
7541
|
+
"Google Ads \u8D26\u6237": "Google Ads account",
|
|
7542
|
+
"TikTok \u5E7F\u544A\u4E3B\u8D26\u6237": "TikTok advertiser",
|
|
7543
|
+
"Bing \u5E7F\u544A\u8D26\u6237": "Bing Ads account",
|
|
7544
|
+
"Meta \u5E7F\u544A\u8D26\u6237": "Meta ad account",
|
|
7545
|
+
"Yandex \u5E7F\u544A\u8D26\u6237": "Yandex Ads account",
|
|
7546
|
+
"Facebook \u5E7F\u544A\u8D26\u6237": "Facebook ad account",
|
|
7547
|
+
"\u5206\u6790\u62A5\u544A": " report",
|
|
7548
|
+
"\u6BCF\u65E5\u8D8B\u52BF": "Daily trend",
|
|
7549
|
+
"\u7CFB\u5217\u8868\u73B0": "Campaigns",
|
|
7550
|
+
"\u4E00\u7EA7\u884C\u653F\u533A": "Admin area",
|
|
7551
|
+
"\u4E0B\u94BB": "drill-down",
|
|
7552
|
+
"\u6682\u65E0\u5EFA\u8BAE": "No recommendation",
|
|
7553
|
+
"\u6682\u65E0\u4F18\u5316\u5EFA\u8BAE": "No recommendation",
|
|
7554
|
+
"\u6682\u65E0\u5206\u6790\u7ED3\u8BBA": "No analysis",
|
|
7555
|
+
"\u6682\u65E0\u6838\u5FC3\u6307\u6807\u6570\u636E": "No KPI data",
|
|
7556
|
+
"\u6682\u65E0\u8D26\u6237\u7ED3\u6784\u6570\u636E": "No structure data",
|
|
7557
|
+
"CLI \u7B80\u6613\u8BCA\u65AD\uFF08Lighthouse API \u5931\u8D25\uFF09": "Simplified diagnosis (Lighthouse API failed)",
|
|
7558
|
+
"\u57FA\u7840\u8FBE\u6807\u3002(Basic compliance.)": "Basic compliance.",
|
|
7559
|
+
"\u826F\u597D\u3002(Good.)": "Good.",
|
|
7560
|
+
"\u6240\u6709\u6307\u6807\u5747\u672A\u8FBE\u6807\uFF0C\u9700\u8981\u5168\u9762\u4F18\u5316\u3002(All metrics failed, comprehensive optimization needed.)": "All metrics failed. A full optimization pass is needed.",
|
|
7561
|
+
"\u6570\u636E\u83B7\u53D6\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7AD9\u914D\u7F6E\u3002(Data fetch failed, please check website configuration.)": "Data fetch failed. Check the site configuration.",
|
|
7562
|
+
"\u4E0D\u5EFA\u8BAE\u6295\u653E\u5E7F\u544A\uFF0C\u9700\u8981\u5168\u9762\u6574\u6539": "Not ready for ads. Fix the site first.",
|
|
7563
|
+
"\u5C0F\u5E45\u4F18\u5316\u540E\u53EF\u76F4\u63A5\u6295\u653E\u5E7F\u544A": "Ready for ads after a few fixes",
|
|
7564
|
+
"\u53EF\u76F4\u63A5\u6295\u653E\u5E7F\u544A": "Ready for ads",
|
|
7565
|
+
"\u6025\u9700\u4F18\u5316\uFF01": "Needs urgent work",
|
|
7566
|
+
"\u9700\u8981\u91CD\u70B9\u4F18\u5316": "Needs focused work",
|
|
7567
|
+
"\u7F51\u7AD9\u8868\u73B0\u4F18\u79C0\uFF0C\u8FDC\u9AD8\u4E8E\u884C\u4E1A\u5E73\u5747\u503C\uFF0C\u53EF\u653E\u5FC3\u5F00\u542F\u5E7F\u544A\u6295\u653E": "The site is well above the industry average and is ready for ads",
|
|
7568
|
+
"\u7F51\u7AD9\u52A0\u8F7D\u901F\u5EA6\u5FEB\uFF0C\u9875\u9762\u54CD\u5E94\u53CA\u65F6\uFF0C\u8FBE\u5230\u884C\u4E1A\u9886\u5148\u6C34\u5E73": "The site loads quickly and is ahead of the industry",
|
|
7569
|
+
"\u7F51\u7AD9\u52A0\u8F7D\u901F\u5EA6\u8F83\u6162\uFF0C\u5EFA\u8BAE\u8FDB\u884C\u5168\u9762\u4F18\u5316\uFF0C\u63D0\u5347\u9875\u9762\u6027\u80FD": "The site is slow. Improve performance before scaling ads",
|
|
7570
|
+
"\u62A5\u544A\u6D4F\u89C8\u903B\u8F91": "How to read this report",
|
|
7571
|
+
"\u6295\u653E\u6548\u7387\u603B\u89C8": "Efficiency overview",
|
|
7572
|
+
"\u9884\u7B97\u82B1\u5728\u54EA\uFF08\u5E7F\u544A\u7C7B\u578B\uFF09": "Where the budget went (ad types)",
|
|
7573
|
+
"\u8BE2\u76D8\u4ECE\u54EA\u6765\uFF08\u533A\u57DF\u7ED3\u6784\uFF09": "Where leads came from (regions)",
|
|
7574
|
+
"\u56FD\u5BB6\u660E\u7EC6\uFF1A\u6D88\u8D39 \xB7 \u8BE2\u76D8 \xB7 \u6210\u672C": "Country detail: spend \xB7 leads \xB7 cost",
|
|
7575
|
+
"\u533A\u57DF\u4E0E\u56FD\u5BB6\uFF1A\u52A0 / \u5B88 / \u780D": "Regions and countries: add / hold / cut",
|
|
7576
|
+
"\u641C\u7D22\u4F18\u5316\u6253\u6CD5\uFF08\u57FA\u672C\u76D8\uFF09": "Search optimization (core)",
|
|
7577
|
+
"\u975E\u641C\u7D22\uFF1A\u6309\u7C7B\u578B\u6267\u884C\u6E05\u5355": "Non-search: action list by type",
|
|
7578
|
+
"\u5468\u8282\u594F\u4E0E\u6267\u884C\u6E05\u5355": "Weekly cadence and action list",
|
|
7579
|
+
"\u6708\u5EA6\u76EE\u6807\u9636\u68AF\uFF08\u5EFA\u8BAE\u6863\u82B1\u8D39\uFF0C\u4E0D\u662F\u5DF2\u6279\u9884\u7B97\uFF09": "Monthly target ladder (suggested spend, not approved budget)",
|
|
7580
|
+
"\u6838\u5FC3 7 \u7EF4\uFF08\u5BF9\u6807\u6295\u653E\u62A5\u8868\uFF09": "7 core metrics (vs the ads report)",
|
|
7581
|
+
"\u6708\u5EA6\u5168\u7EF4\u5EA6\u660E\u7EC6": "Monthly full-dimension detail",
|
|
7582
|
+
"\u5E7F\u544A\u63A2\u7D22\uFF08\u975E\u641C\u7D22\uFF09": "Ad exploration (non-search)",
|
|
7583
|
+
"\u5185\u5BB9\u6C47\u603B\uFF1A\u4EAE\u70B9\u4E0E\u6CE8\u610F": "Highlights and watch-outs",
|
|
7584
|
+
"\u8D26\u6237\u4FA7\u89C2\u5BDF": "Account observations",
|
|
7585
|
+
"\u6570\u636E\u89C4\u5212": "Planning",
|
|
7586
|
+
"\u6570\u636E\u8868\u73B0": "Results",
|
|
7587
|
+
"\u89C4\u5212\u6838\u5FC3": "Plan focus",
|
|
7588
|
+
"\u9884\u7B97\u600E\u4E48\u5206": "How to split the budget",
|
|
7589
|
+
"\u8BE2\u76D8\u6570\u91CF + \u8D28\u91CF": "Lead volume and quality",
|
|
7590
|
+
"\u54C1\u724C\u58F0\u91CF": "Brand reach",
|
|
7591
|
+
"\u914D\u6BD4\u7EAA\u5F8B": "Mix rules",
|
|
7592
|
+
"\u843D\u5730\u9875\u4E0E\u7EBF\u7D22\u8D28\u91CF": "Landing pages and lead quality",
|
|
7593
|
+
"\u53D7\u4F17\u4E0E\u8FD0\u8425\u52A8\u4F5C": "Audiences and ops",
|
|
7594
|
+
"\u89C6\u9891\u53E3\u5F84\uFF08\u4E0D\u662F\u672C\u6237\u89C4\u5212\uFF09": "Video notes (not this account's plan)",
|
|
7595
|
+
"\u4E09\u6708\u8DEF\u7EBF\u56FE": "Three-month roadmap",
|
|
7596
|
+
"\u5EFA\u8BAE\u6863\u6708\u5EA6\u62C6\u5206": "Suggested monthly split",
|
|
7597
|
+
"\u76F8\u5173\u641C\u7D22\u8BCD": "Related search terms",
|
|
7598
|
+
"\u6838\u5FC3\u7ED3\u8BBA": "Key takeaways",
|
|
7599
|
+
"\u9605\u8BFB\u8DEF\u5F84": "Reading path",
|
|
7600
|
+
"\u9884\u7B97\u7ED3\u6784": "Budget mix",
|
|
7601
|
+
"\u533A\u57DF\u7ED3\u6784": "Region mix",
|
|
7602
|
+
"\u56FD\u5BB6\u660E\u7EC6": "Country detail",
|
|
7603
|
+
"\u8D26\u6237\u89C2\u5BDF": "Account notes",
|
|
7604
|
+
"\u7ED3\u6784\u4F18\u5316": "Structure",
|
|
7605
|
+
"\u63A2\u7D22\u843D\u5730": "Exploration",
|
|
7606
|
+
"\u901A\u7528\u5DE1\u68C0": "Routine checks",
|
|
7607
|
+
"\u9884\u7B97\u914D\u6BD4": "Budget mix",
|
|
7608
|
+
"\u5E7F\u544A\u63A2\u7D22": "Ad exploration",
|
|
7609
|
+
"\u8BE2\u76D8\u4FA7\u8865\u5145": "Lead-side extras",
|
|
7610
|
+
"\u76EE\u6807\u5206\u5C42": "Goal tiers",
|
|
7611
|
+
"\u8C22\u8C22": "Thank you"
|
|
7612
|
+
};
|
|
7613
|
+
}
|
|
7614
|
+
});
|
|
7615
|
+
|
|
7616
|
+
// src/report-i18n/html.ts
|
|
7617
|
+
function localizeReportHtml(html, lang) {
|
|
7618
|
+
const withLang = setHtmlLang(html, lang);
|
|
7619
|
+
const phrased = lang === "en" ? applyEnglishPhrases(withLang) : withLang;
|
|
7620
|
+
return injectReportLabels(phrased, lang);
|
|
7621
|
+
}
|
|
7622
|
+
function setHtmlLang(html, lang) {
|
|
7623
|
+
const attr = htmlLangAttr(lang);
|
|
7624
|
+
if (/<html\b[^>]*\blang\s*=/i.test(html)) {
|
|
7625
|
+
return html.replace(/(<html\b[^>]*\blang\s*=\s*)(["'])[^"']*\2/i, `$1"${attr}"`);
|
|
7626
|
+
}
|
|
7627
|
+
return html.replace(/<html\b/i, `<html lang="${attr}"`);
|
|
7628
|
+
}
|
|
7629
|
+
function applyEnglishPhrases(html) {
|
|
7630
|
+
const keys = Object.keys(ENGLISH_PHRASES).filter((key) => key.length >= 2).sort((a, b) => b.length - a.length);
|
|
7631
|
+
let out = html;
|
|
7632
|
+
for (const zh of keys) {
|
|
7633
|
+
const en = ENGLISH_PHRASES[zh];
|
|
7634
|
+
if (!en || en === zh || !out.includes(zh)) continue;
|
|
7635
|
+
out = out.split(zh).join(en);
|
|
7636
|
+
}
|
|
7637
|
+
return out;
|
|
7638
|
+
}
|
|
7639
|
+
function injectReportLabels(html, lang) {
|
|
7640
|
+
const json = JSON.stringify(kpiLabels(lang)).replace(/</g, "\\u003c");
|
|
7641
|
+
const assignment = `window.__REPORT_LABELS__ = ${json};`;
|
|
7642
|
+
if (html.includes(LABELS_MARKER)) return html.replace(LABELS_MARKER, assignment);
|
|
7643
|
+
const tag = `<script>${assignment}</script>`;
|
|
7644
|
+
if (html.includes("</head>")) return html.replace("</head>", `${tag}
|
|
7645
|
+
</head>`);
|
|
7646
|
+
return `${tag}
|
|
7647
|
+
${html}`;
|
|
7648
|
+
}
|
|
7649
|
+
var LABELS_MARKER;
|
|
7650
|
+
var init_html = __esm({
|
|
7651
|
+
"src/report-i18n/html.ts"() {
|
|
7652
|
+
"use strict";
|
|
7653
|
+
init_lang();
|
|
7654
|
+
init_labels();
|
|
7655
|
+
init_phrases_en();
|
|
7656
|
+
LABELS_MARKER = "window.__REPORT_LABELS__ = window.__REPORT_LABELS__ || null;";
|
|
7657
|
+
}
|
|
7658
|
+
});
|
|
7659
|
+
|
|
7232
7660
|
// src/utils/google-analysis-snapshot.ts
|
|
7233
7661
|
var init_google_analysis_snapshot = __esm({
|
|
7234
7662
|
"src/utils/google-analysis-snapshot.ts"() {
|
|
@@ -7579,19 +8007,20 @@ var init_geo_en2zh = __esm({
|
|
|
7579
8007
|
});
|
|
7580
8008
|
|
|
7581
8009
|
// src/commands/report-period.ts
|
|
7582
|
-
function classifyReportPeriod(current, previous) {
|
|
8010
|
+
function classifyReportPeriod(current, previous, lang = "zh") {
|
|
7583
8011
|
const start = tryParse(current?.start);
|
|
7584
8012
|
const end = tryParse(current?.end);
|
|
7585
|
-
if (!start || !end) return customPeriod();
|
|
8013
|
+
if (!start || !end) return customPeriod(lang);
|
|
7586
8014
|
if (isFullCalendarQuarter(start, end)) {
|
|
7587
8015
|
const tag = quarterTagFromMonth(start.m);
|
|
7588
8016
|
const prev = tryParse(previous?.start);
|
|
7589
8017
|
const prevEnd = tryParse(previous?.end);
|
|
7590
8018
|
return {
|
|
7591
8019
|
current: tag,
|
|
7592
|
-
previous: prev && prevEnd && isFullCalendarQuarter(prev, prevEnd) ? quarterTagFromMonth(prev.m) :
|
|
8020
|
+
previous: prev && prevEnd && isFullCalendarQuarter(prev, prevEnd) ? quarterTagFromMonth(prev.m) : priorWord(lang),
|
|
7593
8021
|
next: tag === "Q4" ? "Q1" : `Q${Number(tag.slice(1)) + 1}`,
|
|
7594
|
-
unit: "\u5B63\u5EA6"
|
|
8022
|
+
unit: "\u5B63\u5EA6",
|
|
8023
|
+
unitLabel: lang === "en" ? "Quarterly" : "\u5B63\u5EA6"
|
|
7595
8024
|
};
|
|
7596
8025
|
}
|
|
7597
8026
|
if (start.d === 1 && start.y === end.y && start.m === end.m) {
|
|
@@ -7600,13 +8029,14 @@ function classifyReportPeriod(current, previous) {
|
|
|
7600
8029
|
const prevSameMonth = prev && prevEnd && prev.y === prevEnd.y && prev.m === prevEnd.m;
|
|
7601
8030
|
const nextMonth = start.m === 12 ? 1 : start.m + 1;
|
|
7602
8031
|
return {
|
|
7603
|
-
current:
|
|
7604
|
-
previous: prevSameMonth ?
|
|
7605
|
-
next:
|
|
7606
|
-
unit: "\u6708\u5EA6"
|
|
8032
|
+
current: monthWord(start.m, lang),
|
|
8033
|
+
previous: prevSameMonth ? monthWord(prev.m, lang) : priorWord(lang),
|
|
8034
|
+
next: monthWord(nextMonth, lang),
|
|
8035
|
+
unit: "\u6708\u5EA6",
|
|
8036
|
+
unitLabel: lang === "en" ? "Monthly" : "\u6708\u5EA6"
|
|
7607
8037
|
};
|
|
7608
8038
|
}
|
|
7609
|
-
return customPeriod();
|
|
8039
|
+
return customPeriod(lang);
|
|
7610
8040
|
}
|
|
7611
8041
|
function rangeFromMeta(meta) {
|
|
7612
8042
|
if (!meta || typeof meta !== "object") return null;
|
|
@@ -7614,14 +8044,24 @@ function rangeFromMeta(meta) {
|
|
|
7614
8044
|
if (typeof record2.startDate !== "string" || typeof record2.endDate !== "string") return null;
|
|
7615
8045
|
return { start: record2.startDate, end: record2.endDate };
|
|
7616
8046
|
}
|
|
7617
|
-
function attachPeriodChrome(payload) {
|
|
7618
|
-
return { ...payload, periodChrome: classifyReportPeriod(rangeFromMeta(payload.meta)) };
|
|
8047
|
+
function attachPeriodChrome(payload, lang = "zh") {
|
|
8048
|
+
return { ...payload, periodChrome: classifyReportPeriod(rangeFromMeta(payload.meta), void 0, lang) };
|
|
7619
8049
|
}
|
|
7620
8050
|
function periodWord(unit, neutral) {
|
|
7621
8051
|
return unit || neutral;
|
|
7622
8052
|
}
|
|
7623
|
-
function customPeriod() {
|
|
7624
|
-
|
|
8053
|
+
function customPeriod(lang) {
|
|
8054
|
+
if (lang === "en") {
|
|
8055
|
+
return { current: "This period", previous: "Prior period", next: "Next period", unit: "", unitLabel: "" };
|
|
8056
|
+
}
|
|
8057
|
+
return { current: "\u672C\u671F", previous: "\u4E0A\u671F", next: "\u4E0B\u671F", unit: "", unitLabel: "" };
|
|
8058
|
+
}
|
|
8059
|
+
function priorWord(lang) {
|
|
8060
|
+
return lang === "en" ? "Prior period" : "\u4E0A\u671F";
|
|
8061
|
+
}
|
|
8062
|
+
function monthWord(month, lang) {
|
|
8063
|
+
if (lang === "en") return MONTHS_EN[month - 1] ?? String(month);
|
|
8064
|
+
return `${month}\u6708`;
|
|
7625
8065
|
}
|
|
7626
8066
|
function tryParse(iso) {
|
|
7627
8067
|
if (!iso) return null;
|
|
@@ -7644,10 +8084,11 @@ function isFullCalendarQuarter(start, end) {
|
|
|
7644
8084
|
function quarterTagFromMonth(month) {
|
|
7645
8085
|
return `Q${Math.ceil(month / 3)}`;
|
|
7646
8086
|
}
|
|
7647
|
-
var DATE_RE2;
|
|
8087
|
+
var MONTHS_EN, DATE_RE2;
|
|
7648
8088
|
var init_report_period = __esm({
|
|
7649
8089
|
"src/commands/report-period.ts"() {
|
|
7650
8090
|
"use strict";
|
|
8091
|
+
MONTHS_EN = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
7651
8092
|
DATE_RE2 = /^(\d{4})-(\d{2})-(\d{2})/;
|
|
7652
8093
|
}
|
|
7653
8094
|
});
|
|
@@ -103235,19 +103676,20 @@ var init_city_to_country = __esm({
|
|
|
103235
103676
|
});
|
|
103236
103677
|
|
|
103237
103678
|
// src/commands/google-analysis/format-campaign-status.ts
|
|
103238
|
-
function formatGoogleCampaignStatusDisplay(status) {
|
|
103679
|
+
function formatGoogleCampaignStatusDisplay(status, lang = "zh") {
|
|
103239
103680
|
if (status == null) return "\u2014";
|
|
103240
103681
|
const raw = String(status).trim();
|
|
103241
103682
|
if (raw === "") return "\u2014";
|
|
103683
|
+
const en = lang === "en";
|
|
103242
103684
|
switch (raw.toUpperCase()) {
|
|
103243
103685
|
case "ENABLED":
|
|
103244
|
-
return "\u6295\u653E\u4E2D";
|
|
103686
|
+
return en ? "Active" : "\u6295\u653E\u4E2D";
|
|
103245
103687
|
case "PAUSED":
|
|
103246
|
-
return "\u5DF2\u6682\u505C";
|
|
103688
|
+
return en ? "Paused" : "\u5DF2\u6682\u505C";
|
|
103247
103689
|
case "REMOVED":
|
|
103248
|
-
return "\u5DF2\u79FB\u9664";
|
|
103690
|
+
return en ? "Removed" : "\u5DF2\u79FB\u9664";
|
|
103249
103691
|
default:
|
|
103250
|
-
return "\u672A\u77E5";
|
|
103692
|
+
return en ? "Unknown" : "\u672A\u77E5";
|
|
103251
103693
|
}
|
|
103252
103694
|
}
|
|
103253
103695
|
function readGoogleCampaignStatusRaw(row) {
|
|
@@ -104558,17 +105000,31 @@ function formatOkkiZhDateRange(start, end) {
|
|
|
104558
105000
|
if (!a || !b) return [start, end].filter(Boolean).join(" - ") || "\u2014";
|
|
104559
105001
|
return `${a.y}\u5E74${a.m}\u6708${a.d}\u65E5 - ${b.y}\u5E74${b.m}\u6708${b.d}\u65E5`;
|
|
104560
105002
|
}
|
|
104561
|
-
function formatOkkiReviewTitle(endDate) {
|
|
105003
|
+
function formatOkkiReviewTitle(endDate, lang = "zh") {
|
|
104562
105004
|
const parsed = parseYmd(endDate);
|
|
104563
105005
|
const month = parsed?.m ?? Number(String(endDate).split("-")[1]);
|
|
104564
|
-
if (!Number.isFinite(month) || month < 1) return "\u6570\u636E\u590D\u76D8\uFF1A";
|
|
105006
|
+
if (!Number.isFinite(month) || month < 1) return lang === "en" ? "Performance review:" : "\u6570\u636E\u590D\u76D8\uFF1A";
|
|
105007
|
+
if (lang === "en") return `Performance review for month ${month}:`;
|
|
104565
105008
|
return `${month}\u6708\u4EFD\u6570\u636E\u590D\u76D8\uFF1A`;
|
|
104566
105009
|
}
|
|
104567
|
-
function
|
|
105010
|
+
function formatOkkiDateRange(start, end, lang) {
|
|
105011
|
+
if (lang !== "en") return formatOkkiZhDateRange(start, end);
|
|
105012
|
+
const a = parseYmd(start);
|
|
105013
|
+
const b = parseYmd(end);
|
|
105014
|
+
if (!a || !b) return [start, end].filter(Boolean).join(" - ") || "\u2014";
|
|
105015
|
+
const iso = (p) => `${p.y}-${String(p.m).padStart(2, "0")}-${String(p.d).padStart(2, "0")}`;
|
|
105016
|
+
return `${iso(a)} \u2013 ${iso(b)}`;
|
|
105017
|
+
}
|
|
105018
|
+
function deviceLabel(value, lang) {
|
|
104568
105019
|
const raw = str(value);
|
|
105020
|
+
if (lang === "en") return raw || "\u2014";
|
|
104569
105021
|
return DEVICE_TYPE_ZH[raw] ?? raw;
|
|
104570
105022
|
}
|
|
104571
|
-
function targetingStatus(row) {
|
|
105023
|
+
function targetingStatus(row, lang = "zh") {
|
|
105024
|
+
if (lang === "en") {
|
|
105025
|
+
const raw2 = row.queryTargetingStatus ?? row.matchType;
|
|
105026
|
+
if (textLen(raw2)) return String(raw2).trim();
|
|
105027
|
+
}
|
|
104572
105028
|
if (textLen(row.queryTargetingStatusZh)) return String(row.queryTargetingStatusZh).trim();
|
|
104573
105029
|
const raw = str(row.queryTargetingStatus, "");
|
|
104574
105030
|
return TARGETING_STATUS_ZH[raw] ?? (raw || "\u2014");
|
|
@@ -104657,10 +105113,11 @@ function campaignRows(data) {
|
|
|
104657
105113
|
]
|
|
104658
105114
|
};
|
|
104659
105115
|
}
|
|
104660
|
-
function keywordRows(data) {
|
|
105116
|
+
function keywordRows(data, lang = "zh") {
|
|
105117
|
+
const matchOf = (row) => lang === "en" ? row.keywordMatchType || row.keywordMatchTypeZh : row.keywordMatchTypeZh || row.keywordMatchType;
|
|
104661
105118
|
return sortBySpendDesc(data.tables?.keywords ?? []).map((row) => [
|
|
104662
|
-
formatOkkiKeywordDisplay(row.keyword, row
|
|
104663
|
-
str(row
|
|
105119
|
+
formatOkkiKeywordDisplay(row.keyword, matchOf(row)),
|
|
105120
|
+
str(matchOf(row)),
|
|
104664
105121
|
str(row.campaignName),
|
|
104665
105122
|
str(row.adGroupName),
|
|
104666
105123
|
money(row.spend),
|
|
@@ -104673,16 +105130,16 @@ function keywordRows(data) {
|
|
|
104673
105130
|
rate(row.conversionRate)
|
|
104674
105131
|
]);
|
|
104675
105132
|
}
|
|
104676
|
-
function searchTermRows(data) {
|
|
105133
|
+
function searchTermRows(data, lang = "zh") {
|
|
104677
105134
|
return sortBySpendDesc(data.tables?.searchTerms ?? []).map((row) => [
|
|
104678
105135
|
str(row.searchTermText),
|
|
104679
|
-
str(row.matchTypeZh || row.matchType),
|
|
104680
|
-
targetingStatus(row),
|
|
105136
|
+
str(lang === "en" ? row.matchType || row.matchTypeZh : row.matchTypeZh || row.matchType),
|
|
105137
|
+
targetingStatus(row, lang),
|
|
104681
105138
|
str(row.campaignName),
|
|
104682
105139
|
str(row.adGroupName),
|
|
104683
105140
|
formatOkkiKeywordDisplay(
|
|
104684
105141
|
row.keywordText || row.keyword,
|
|
104685
|
-
row.keywordMatchTypeZh || row.keywordMatchType || row.matchTypeZh || row.matchType
|
|
105142
|
+
lang === "en" ? row.keywordMatchType || row.keywordMatchTypeZh || row.matchType || row.matchTypeZh : row.keywordMatchTypeZh || row.keywordMatchType || row.matchTypeZh || row.matchType
|
|
104686
105143
|
),
|
|
104687
105144
|
count(row.impressions),
|
|
104688
105145
|
count(row.clicks),
|
|
@@ -104694,11 +105151,11 @@ function searchTermRows(data) {
|
|
|
104694
105151
|
rate(row.conversionRate)
|
|
104695
105152
|
]);
|
|
104696
105153
|
}
|
|
104697
|
-
function deviceRows(data) {
|
|
105154
|
+
function deviceRows(data, lang = "zh") {
|
|
104698
105155
|
return sortBySpendDesc(data.tables?.devices ?? []).map((row) => {
|
|
104699
105156
|
const pair = conversionsPair(row);
|
|
104700
105157
|
return [
|
|
104701
|
-
deviceLabel(row.deviceType),
|
|
105158
|
+
deviceLabel(row.deviceType, lang),
|
|
104702
105159
|
"\u5E7F\u544A\u7CFB\u5217",
|
|
104703
105160
|
str(row.campaignName),
|
|
104704
105161
|
str(row.bidModifierDisplay, "\u2014"),
|
|
@@ -104714,13 +105171,15 @@ function deviceRows(data) {
|
|
|
104714
105171
|
];
|
|
104715
105172
|
});
|
|
104716
105173
|
}
|
|
104717
|
-
function geoRows(data) {
|
|
105174
|
+
function geoRows(data, lang = "zh") {
|
|
104718
105175
|
return sortBySpendDesc(data.tables?.geo ?? []).map((row) => {
|
|
104719
105176
|
const pair = conversionsPair(row);
|
|
104720
105177
|
const impressions = num6(row.impressions) ?? 0;
|
|
104721
105178
|
const interactions = okkiGeoInteractionCount(row);
|
|
104722
105179
|
return [
|
|
104723
|
-
str(
|
|
105180
|
+
str(
|
|
105181
|
+
lang === "en" ? row.countryOrRegion || row.countryNameZh : row.countryOrRegionZh || row.countryNameZh || row.countryOrRegion
|
|
105182
|
+
),
|
|
104724
105183
|
str(row.campaignName),
|
|
104725
105184
|
count(row.impressions),
|
|
104726
105185
|
interactions > 0 ? count(interactions) : 0,
|
|
@@ -104736,9 +105195,9 @@ function geoRows(data) {
|
|
|
104736
105195
|
];
|
|
104737
105196
|
});
|
|
104738
105197
|
}
|
|
104739
|
-
function buildOkkiWeeklySheetDrafts(data) {
|
|
105198
|
+
function buildOkkiWeeklySheetDrafts(data, lang = "zh") {
|
|
104740
105199
|
const meta = asRecord21(data.meta) ?? {};
|
|
104741
|
-
const period =
|
|
105200
|
+
const period = formatOkkiDateRange(str(meta.startDate, ""), str(meta.endDate, ""), lang);
|
|
104742
105201
|
const campaigns = campaignRows(data);
|
|
104743
105202
|
const drafts = {
|
|
104744
105203
|
campaigns: {
|
|
@@ -104762,7 +105221,7 @@ function buildOkkiWeeklySheetDrafts(data) {
|
|
|
104762
105221
|
dataRows: campaigns.body,
|
|
104763
105222
|
totalRow: campaigns.total,
|
|
104764
105223
|
analysisLines: analysisLines(data, "campaigns"),
|
|
104765
|
-
reviewTitle: formatOkkiReviewTitle(str(meta.endDate, "")),
|
|
105224
|
+
reviewTitle: formatOkkiReviewTitle(str(meta.endDate, ""), lang),
|
|
104766
105225
|
reviewLines: reviewLines(data)
|
|
104767
105226
|
},
|
|
104768
105227
|
keywords: {
|
|
@@ -104784,7 +105243,7 @@ function buildOkkiWeeklySheetDrafts(data) {
|
|
|
104784
105243
|
"\u8F6C\u5316\u7387"
|
|
104785
105244
|
],
|
|
104786
105245
|
colWidths: [28, 12, 24, 20, 11, 11, 10, 9, 16, 10, 14, 9],
|
|
104787
|
-
dataRows: keywordRows(data),
|
|
105246
|
+
dataRows: keywordRows(data, lang),
|
|
104788
105247
|
analysisLines: analysisLines(data, "keywords")
|
|
104789
105248
|
},
|
|
104790
105249
|
searchTerms: {
|
|
@@ -104808,7 +105267,7 @@ function buildOkkiWeeklySheetDrafts(data) {
|
|
|
104808
105267
|
"\u8F6C\u5316\u7387"
|
|
104809
105268
|
],
|
|
104810
105269
|
colWidths: [26, 12, 14, 22, 18, 22, 11, 10, 9, 16, 11, 10, 14, 9],
|
|
104811
|
-
dataRows: searchTermRows(data),
|
|
105270
|
+
dataRows: searchTermRows(data, lang),
|
|
104812
105271
|
analysisLines: analysisLines(data, "searchTerms")
|
|
104813
105272
|
},
|
|
104814
105273
|
devices: {
|
|
@@ -104831,7 +105290,7 @@ function buildOkkiWeeklySheetDrafts(data) {
|
|
|
104831
105290
|
"\u8F6C\u5316\u7387"
|
|
104832
105291
|
],
|
|
104833
105292
|
colWidths: [12, 10, 26, 12, 11, 10, 9, 16, 11, 14, 10, 14, 9],
|
|
104834
|
-
dataRows: deviceRows(data),
|
|
105293
|
+
dataRows: deviceRows(data, lang),
|
|
104835
105294
|
analysisLines: analysisLines(data, "devices")
|
|
104836
105295
|
},
|
|
104837
105296
|
geo: {
|
|
@@ -104854,15 +105313,26 @@ function buildOkkiWeeklySheetDrafts(data) {
|
|
|
104854
105313
|
"\u8F6C\u5316\u7387"
|
|
104855
105314
|
],
|
|
104856
105315
|
colWidths: [16, 26, 11, 11, 9, 11, 11, 10, 9, 14, 10, 14, 9],
|
|
104857
|
-
dataRows: geoRows(data),
|
|
105316
|
+
dataRows: geoRows(data, lang),
|
|
104858
105317
|
analysisLines: analysisLines(data, "geo")
|
|
104859
105318
|
}
|
|
104860
105319
|
};
|
|
104861
|
-
return OKKI_SHEET_KEYS.map((key) => drafts[key]);
|
|
105320
|
+
return OKKI_SHEET_KEYS.map((key) => localizeOkkiDraft(drafts[key], lang));
|
|
105321
|
+
}
|
|
105322
|
+
function localizeOkkiDraft(draft, lang) {
|
|
105323
|
+
if (lang !== "en") return draft;
|
|
105324
|
+
const text3 = (value) => applyEnglishPhrases(value);
|
|
105325
|
+
return {
|
|
105326
|
+
...draft,
|
|
105327
|
+
name: text3(draft.name),
|
|
105328
|
+
title: text3(draft.title),
|
|
105329
|
+
headers: draft.headers.map(text3),
|
|
105330
|
+
reviewTitle: draft.reviewTitle ? text3(draft.reviewTitle) : draft.reviewTitle
|
|
105331
|
+
};
|
|
104862
105332
|
}
|
|
104863
|
-
function writeOkkiWeeklyExcel(outPath, data) {
|
|
105333
|
+
function writeOkkiWeeklyExcel(outPath, data, lang = "zh") {
|
|
104864
105334
|
const wb = createExcelWorkbook({ accent: "google" });
|
|
104865
|
-
for (const draft of buildOkkiWeeklySheetDrafts(data)) {
|
|
105335
|
+
for (const draft of buildOkkiWeeklySheetDrafts(data, lang)) {
|
|
104866
105336
|
const sheet = wb.addSheet(draft.name);
|
|
104867
105337
|
const span = draft.headers.length;
|
|
104868
105338
|
sheet.setColWidths(draft.colWidths);
|
|
@@ -104876,7 +105346,7 @@ function writeOkkiWeeklyExcel(outPath, data) {
|
|
|
104876
105346
|
sheet.dataRow(draft.totalRow, { labelColumns: [0] });
|
|
104877
105347
|
}
|
|
104878
105348
|
sheet.blankRow();
|
|
104879
|
-
sheet.sectionBar("\u5206\u6790", { span });
|
|
105349
|
+
sheet.sectionBar(lang === "en" ? "Analysis" : "\u5206\u6790", { span });
|
|
104880
105350
|
for (const line of draft.analysisLines) {
|
|
104881
105351
|
sheet.noteRow(line, span);
|
|
104882
105352
|
}
|
|
@@ -104894,6 +105364,7 @@ var REVIEW_LABELS2, DEVICE_TYPE_ZH, TARGETING_STATUS_ZH;
|
|
|
104894
105364
|
var init_okki_render_excel = __esm({
|
|
104895
105365
|
"src/commands/google-analysis/okki-render-excel.ts"() {
|
|
104896
105366
|
"use strict";
|
|
105367
|
+
init_html();
|
|
104897
105368
|
init_xlsx_style_engine();
|
|
104898
105369
|
init_okki_display();
|
|
104899
105370
|
init_okki_report_content();
|
|
@@ -104960,6 +105431,7 @@ async function runGoogleAnalysisOkkiRender(opts) {
|
|
|
104960
105431
|
`);
|
|
104961
105432
|
process.exit(1);
|
|
104962
105433
|
}
|
|
105434
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
104963
105435
|
const contentCheck = validateOkkiWeeklyReportContent(data);
|
|
104964
105436
|
if (!contentCheck.ok) {
|
|
104965
105437
|
console.error(`
|
|
@@ -104976,7 +105448,7 @@ async function runGoogleAnalysisOkkiRender(opts) {
|
|
|
104976
105448
|
opts.out ?? path35.join(path35.dirname(dataPath), "okki-weekly-report.xlsx")
|
|
104977
105449
|
);
|
|
104978
105450
|
await fs30.mkdir(path35.dirname(outPath), { recursive: true });
|
|
104979
|
-
writeOkkiWeeklyExcel(outPath, data);
|
|
105451
|
+
writeOkkiWeeklyExcel(outPath, data, lang);
|
|
104980
105452
|
console.log(`
|
|
104981
105453
|
\u2705 OKKI \u5468\u62A5\u5DF2\u751F\u6210\uFF1A${outPath}
|
|
104982
105454
|
`);
|
|
@@ -104988,6 +105460,7 @@ var init_okki_render_report = __esm({
|
|
|
104988
105460
|
init_okki_merge_snapshot();
|
|
104989
105461
|
init_okki_report_content();
|
|
104990
105462
|
init_okki_render_excel();
|
|
105463
|
+
init_lang();
|
|
104991
105464
|
}
|
|
104992
105465
|
});
|
|
104993
105466
|
|
|
@@ -105180,12 +105653,13 @@ function asRecord23(value) {
|
|
|
105180
105653
|
}
|
|
105181
105654
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
105182
105655
|
}
|
|
105183
|
-
function injectReportData2(html, payload) {
|
|
105184
|
-
const
|
|
105185
|
-
|
|
105656
|
+
function injectReportData2(html, payload, lang) {
|
|
105657
|
+
const localized = localizeReportHtml(html, lang);
|
|
105658
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
105659
|
+
if (!localized.includes(INJECT_MARKER)) {
|
|
105186
105660
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 google-period-report.html");
|
|
105187
105661
|
}
|
|
105188
|
-
return
|
|
105662
|
+
return localized.replace(INJECT_MARKER, `window.__GOOGLE_PERIOD_REPORT__ = ${json};`);
|
|
105189
105663
|
}
|
|
105190
105664
|
async function runGoogleAnalysisRender(opts) {
|
|
105191
105665
|
const dataPath = path36.resolve(opts.dataFile);
|
|
@@ -105193,6 +105667,7 @@ async function runGoogleAnalysisRender(opts) {
|
|
|
105193
105667
|
if (opts.snapshotDir?.trim()) {
|
|
105194
105668
|
data = await mergeGoogleAnalysisSnapshotIntoReport(data, path36.resolve(opts.snapshotDir));
|
|
105195
105669
|
}
|
|
105670
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
105196
105671
|
const contentCheck = validateGooglePeriodReportContent(data);
|
|
105197
105672
|
if (!contentCheck.ok) {
|
|
105198
105673
|
console.error(`
|
|
@@ -105222,7 +105697,7 @@ async function runGoogleAnalysisRender(opts) {
|
|
|
105222
105697
|
);
|
|
105223
105698
|
const outDir = path36.dirname(outPath);
|
|
105224
105699
|
await fsPromises2.mkdir(outDir, { recursive: true });
|
|
105225
|
-
await fsPromises2.writeFile(outPath, injectReportData2(html, data), "utf8");
|
|
105700
|
+
await fsPromises2.writeFile(outPath, injectReportData2(html, data, lang), "utf8");
|
|
105226
105701
|
const { stats } = contentCheck;
|
|
105227
105702
|
const cover = periodWord(attachPeriodChrome(data).periodChrome.unit, "\u5468\u671F");
|
|
105228
105703
|
console.log(`
|
|
@@ -105243,6 +105718,8 @@ var init_render_report = __esm({
|
|
|
105243
105718
|
init_merge_snapshot();
|
|
105244
105719
|
init_report_content();
|
|
105245
105720
|
init_report_period();
|
|
105721
|
+
init_lang();
|
|
105722
|
+
init_html();
|
|
105246
105723
|
TEMPLATE_BASENAME = "google-period-report.html";
|
|
105247
105724
|
INJECT_MARKER = "window.__GOOGLE_PERIOD_REPORT__ = window.__GOOGLE_PERIOD_REPORT__ || null;";
|
|
105248
105725
|
}
|
|
@@ -106829,11 +107306,12 @@ function registerGoogleAnalysisCommands(program2) {
|
|
|
106829
107306
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 google-period-report.json").option(
|
|
106830
107307
|
"--snapshot-dir <dir>",
|
|
106831
107308
|
"\u53EF\u9009\uFF1Agoogle-analysis --json-out \u76EE\u5F55\uFF0C\u81EA\u52A8\u5408\u5E76 KPI / \u56FE\u8868 / \u8868\u683C"
|
|
106832
|
-
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
107309
|
+
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
106833
107310
|
await runGoogleAnalysisRender({
|
|
106834
107311
|
dataFile: opts.data,
|
|
106835
107312
|
snapshotDir: opts.snapshotDir,
|
|
106836
|
-
out: opts.out
|
|
107313
|
+
out: opts.out,
|
|
107314
|
+
lang: opts.lang
|
|
106837
107315
|
});
|
|
106838
107316
|
});
|
|
106839
107317
|
root.command("okki-render").description(
|
|
@@ -106841,11 +107319,12 @@ function registerGoogleAnalysisCommands(program2) {
|
|
|
106841
107319
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 okki-weekly-report.json").requiredOption(
|
|
106842
107320
|
"--snapshot-dir <dir>",
|
|
106843
107321
|
"google-analysis --json-out \u76EE\u5F55\uFF08\u987B\u542B campaigns / keywords / search-terms / campaign-device / geo-targeted\uFF09"
|
|
106844
|
-
).option("--out <file>", "\u8F93\u51FA xlsx \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\u7684 okki-weekly-report.xlsx\uFF09").action(async (opts) => {
|
|
107322
|
+
).option("--out <file>", "\u8F93\u51FA xlsx \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\u7684 okki-weekly-report.xlsx\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
106845
107323
|
await runGoogleAnalysisOkkiRender({
|
|
106846
107324
|
dataFile: opts.data,
|
|
106847
107325
|
snapshotDir: opts.snapshotDir,
|
|
106848
|
-
out: opts.out
|
|
107326
|
+
out: opts.out,
|
|
107327
|
+
lang: opts.lang
|
|
106849
107328
|
});
|
|
106850
107329
|
});
|
|
106851
107330
|
}
|
|
@@ -109378,15 +109857,20 @@ function cell(value) {
|
|
|
109378
109857
|
function label(hit) {
|
|
109379
109858
|
return hit.advertiserName || hit.name || "-";
|
|
109380
109859
|
}
|
|
109381
|
-
function buildBalanceScanDelivery(items3, dataIssueMessage) {
|
|
109860
|
+
function buildBalanceScanDelivery(items3, dataIssueMessage, lang = "zh") {
|
|
109861
|
+
const en = lang === "en";
|
|
109382
109862
|
if (dataIssueMessage) {
|
|
109383
109863
|
return { allClear: false, userDelivery: dataIssueMessage, deliveryRule: DELIVERY_RULE };
|
|
109384
109864
|
}
|
|
109385
109865
|
const hits = items3.filter((row) => row.hitReason !== "none");
|
|
109386
109866
|
if (hits.length === 0) {
|
|
109387
|
-
return {
|
|
109867
|
+
return {
|
|
109868
|
+
allClear: true,
|
|
109869
|
+
userDelivery: en ? "No hits today" : PATROL_ALL_CLEAR,
|
|
109870
|
+
deliveryRule: DELIVERY_RULE
|
|
109871
|
+
};
|
|
109388
109872
|
}
|
|
109389
|
-
const header = "| \u8D26\u6237\u540D\u79F0 | \u8D26\u6237ID | \u4F59\u989D | \u5E01\u79CD |\n| --- | --- | ---: | --- |";
|
|
109873
|
+
const header = en ? "| Account | Account ID | Balance | Currency |\n| --- | --- | ---: | --- |" : "| \u8D26\u6237\u540D\u79F0 | \u8D26\u6237ID | \u4F59\u989D | \u5E01\u79CD |\n| --- | --- | ---: | --- |";
|
|
109390
109874
|
const lines = hits.map((h) => {
|
|
109391
109875
|
const balance = h.balance == null ? "\u2014" : String(h.balance);
|
|
109392
109876
|
return `| ${cell(label(h))} | ${h.mediaCustomerId} | ${balance} | ${h.currencyCode ?? "\u2014"} |`;
|
|
@@ -109636,6 +110120,7 @@ function evaluateBalanceScanAccounts(params) {
|
|
|
109636
110120
|
}
|
|
109637
110121
|
|
|
109638
110122
|
// src/commands/balance-scan/run.ts
|
|
110123
|
+
init_lang();
|
|
109639
110124
|
async function runBalanceScan(opts) {
|
|
109640
110125
|
let config = loadConfig(opts.token);
|
|
109641
110126
|
if (opts.refreshDp) {
|
|
@@ -109800,7 +110285,8 @@ async function runBalanceScan(opts) {
|
|
|
109800
110285
|
totalReported: total ?? null,
|
|
109801
110286
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
109802
110287
|
};
|
|
109803
|
-
const
|
|
110288
|
+
const lang = readReportLangOrExit({ flag: opts.lang });
|
|
110289
|
+
const agentBrief = buildBalanceScanDelivery(evaluated, dataIssue?.message ?? null, lang);
|
|
109804
110290
|
const scanPayload = { ok: !dataIssue, data: { items: evaluated }, meta, agentBrief };
|
|
109805
110291
|
const wroteJson = await emitCliJsonOrSnapshot(opts, {
|
|
109806
110292
|
section: `balance-scan-${media}`,
|
|
@@ -109912,7 +110398,7 @@ function register9(program2) {
|
|
|
109912
110398
|
"--json-out <path>",
|
|
109913
110399
|
"\u843D\u76D8\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\u8DEF\u5F84\uFF09\u5E76\u66F4\u65B0 cli-manifest[-<\u67E5\u8BE2id>].json\uFF1B\u76EE\u5F55\u6A21\u5F0F\u6587\u4EF6\u540D\u4E3A `<section>[-<\u67E5\u8BE2id>].json`\uFF1Bstdout \u4E00\u884C\u6458\u8981 JSON\uFF0C\u542B outlineFile\uFF08TS \u5F0F\u7C7B\u578B\u5728 `*.outline.txt`\uFF09",
|
|
109914
110400
|
void 0
|
|
109915
|
-
).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission \u540E\u518D\u626B\u63CF\uFF08\u6392\u67E5\u4F1A\u8BDD\u5F02\u5E38\uFF09", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
110401
|
+
).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission \u540E\u518D\u626B\u63CF\uFF08\u6392\u67E5\u4F1A\u8BDD\u5F02\u5E38\uFF09", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).option("--lang <lang>", "\u4EA4\u7ED9\u7528\u6237\u7684\u53E5\u5B50\u8BED\u8A00\uFF1Azh \u6216 en\uFF0C\u9ED8\u8BA4 zh").action(
|
|
109916
110402
|
async (opts) => {
|
|
109917
110403
|
await runBalanceScan({
|
|
109918
110404
|
token: opts.token,
|
|
@@ -109928,7 +110414,8 @@ function register9(program2) {
|
|
|
109928
110414
|
jsonOut: opts.jsonOut,
|
|
109929
110415
|
refreshDp: opts.refreshDp,
|
|
109930
110416
|
verbose: opts.verbose,
|
|
109931
|
-
loginCustomerId: opts.loginCustomerId
|
|
110417
|
+
loginCustomerId: opts.loginCustomerId,
|
|
110418
|
+
lang: opts.lang
|
|
109932
110419
|
});
|
|
109933
110420
|
}
|
|
109934
110421
|
);
|
|
@@ -110084,11 +110571,15 @@ var PATROL_ALL_CLEAR2 = "\u4ECA\u65E5\u65E0\u547D\u4E2D";
|
|
|
110084
110571
|
function cell2(value) {
|
|
110085
110572
|
return value.replace(/\|/g, "\uFF5C").replace(/\r?\n/g, " ");
|
|
110086
110573
|
}
|
|
110087
|
-
function buildBudgetCircuitDelivery(hits) {
|
|
110574
|
+
function buildBudgetCircuitDelivery(hits, lang = "zh") {
|
|
110088
110575
|
if (hits.length === 0) {
|
|
110089
|
-
return {
|
|
110576
|
+
return {
|
|
110577
|
+
allClear: true,
|
|
110578
|
+
userDelivery: lang === "en" ? "No hits today" : PATROL_ALL_CLEAR2,
|
|
110579
|
+
deliveryRule: DELIVERY_RULE2
|
|
110580
|
+
};
|
|
110090
110581
|
}
|
|
110091
|
-
const header = "| \u7CFB\u5217\u540D\u79F0 | \u7CFB\u5217ID | \u8D26\u6237ID | \u5F53\u65E5\u82B1\u8D39 | \u65E5\u9884\u7B97 |\n| --- | --- | --- | ---: | ---: |";
|
|
110582
|
+
const header = lang === "en" ? "| Campaign | Campaign ID | Account ID | Spend today | Daily budget |\n| --- | --- | --- | ---: | ---: |" : "| \u7CFB\u5217\u540D\u79F0 | \u7CFB\u5217ID | \u8D26\u6237ID | \u5F53\u65E5\u82B1\u8D39 | \u65E5\u9884\u7B97 |\n| --- | --- | --- | ---: | ---: |";
|
|
110092
110583
|
const lines = hits.map(
|
|
110093
110584
|
(h) => `| ${cell2(h.campaignName)} | ${h.campaignId} | ${h.mediaCustomerId} | ${h.spend} | ${h.budget} |`
|
|
110094
110585
|
);
|
|
@@ -110098,11 +110589,15 @@ function buildBudgetCircuitDelivery(hits) {
|
|
|
110098
110589
|
deliveryRule: DELIVERY_RULE2
|
|
110099
110590
|
};
|
|
110100
110591
|
}
|
|
110101
|
-
function buildZeroConvDelivery(hits) {
|
|
110592
|
+
function buildZeroConvDelivery(hits, lang = "zh") {
|
|
110102
110593
|
if (hits.length === 0) {
|
|
110103
|
-
return {
|
|
110594
|
+
return {
|
|
110595
|
+
allClear: true,
|
|
110596
|
+
userDelivery: lang === "en" ? "No hits today" : PATROL_ALL_CLEAR2,
|
|
110597
|
+
deliveryRule: DELIVERY_RULE2
|
|
110598
|
+
};
|
|
110104
110599
|
}
|
|
110105
|
-
const header = "| \u5BF9\u8C61\u540D\u79F0 | \u5BF9\u8C61ID | \u8D26\u6237ID | \u5F53\u65E5\u82B1\u8D39 |\n| --- | --- | --- | ---: |";
|
|
110600
|
+
const header = lang === "en" ? "| Name | ID | Account ID | Spend today |\n| --- | --- | --- | ---: |" : "| \u5BF9\u8C61\u540D\u79F0 | \u5BF9\u8C61ID | \u8D26\u6237ID | \u5F53\u65E5\u82B1\u8D39 |\n| --- | --- | --- | ---: |";
|
|
110106
110601
|
const lines = hits.map(
|
|
110107
110602
|
(h) => `| ${cell2(h.objectName)} | ${h.objectId} | ${h.mediaCustomerId} | ${h.spend} |`
|
|
110108
110603
|
);
|
|
@@ -110113,6 +110608,9 @@ function buildZeroConvDelivery(hits) {
|
|
|
110113
110608
|
};
|
|
110114
110609
|
}
|
|
110115
110610
|
|
|
110611
|
+
// src/commands/guard/budget-circuit.ts
|
|
110612
|
+
init_lang();
|
|
110613
|
+
|
|
110116
110614
|
// src/commands/guard/rules.ts
|
|
110117
110615
|
function moneyGte(leftYuan, rightYuan) {
|
|
110118
110616
|
return Math.round(leftYuan * 100) >= Math.round(rightYuan * 100);
|
|
@@ -110245,7 +110743,7 @@ async function runBudgetCircuit(opts) {
|
|
|
110245
110743
|
},
|
|
110246
110744
|
hits,
|
|
110247
110745
|
errors,
|
|
110248
|
-
agentBrief: buildBudgetCircuitDelivery(hits)
|
|
110746
|
+
agentBrief: buildBudgetCircuitDelivery(hits, readReportLangOrExit({ flag: opts.lang }))
|
|
110249
110747
|
};
|
|
110250
110748
|
const agentBrief = payload.agentBrief;
|
|
110251
110749
|
if (await emitCliJsonOrSnapshot(opts, {
|
|
@@ -110290,6 +110788,7 @@ async function runBudgetCircuit(opts) {
|
|
|
110290
110788
|
|
|
110291
110789
|
// src/commands/guard/zero-conv.ts
|
|
110292
110790
|
init_cli_json_snapshot();
|
|
110791
|
+
init_lang();
|
|
110293
110792
|
function parseLevel(raw) {
|
|
110294
110793
|
const v = (raw ?? "adgroup").toLowerCase();
|
|
110295
110794
|
if (v === "adgroup" || v === "ad" || v === "both") return v;
|
|
@@ -110443,7 +110942,7 @@ async function runZeroConv(opts) {
|
|
|
110443
110942
|
hits,
|
|
110444
110943
|
skipped,
|
|
110445
110944
|
errors,
|
|
110446
|
-
agentBrief: buildZeroConvDelivery(hits)
|
|
110945
|
+
agentBrief: buildZeroConvDelivery(hits, readReportLangOrExit({ flag: opts.lang }))
|
|
110447
110946
|
};
|
|
110448
110947
|
await emitCliJsonOrSnapshot(opts, {
|
|
110449
110948
|
section: "guard-zero-conv",
|
|
@@ -110498,7 +110997,7 @@ function register11(program2) {
|
|
|
110498
110997
|
"--json-out <path>",
|
|
110499
110998
|
"\u843D\u76D8\u76EE\u5F55\u6216 *.json\uFF1Bstdout \u4E00\u884C\u6458\u8981\uFF1B\u4EBA\u7C7B\u53EF\u8BFB\u8868\u59CB\u7EC8\u6253\u5370",
|
|
110500
110999
|
void 0
|
|
110501
|
-
).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF", false).action(
|
|
111000
|
+
).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF", false).option("--lang <lang>", "\u4EA4\u7ED9\u7528\u6237\u7684\u53E5\u5B50\u8BED\u8A00\uFF1Azh \u6216 en\uFF0C\u9ED8\u8BA4 zh").action(
|
|
110502
111001
|
async (opts) => {
|
|
110503
111002
|
await runBudgetCircuit({
|
|
110504
111003
|
media: opts.media,
|
|
@@ -110512,7 +111011,8 @@ function register11(program2) {
|
|
|
110512
111011
|
jsonOut: opts.jsonOut,
|
|
110513
111012
|
refreshDp: opts.refreshDp,
|
|
110514
111013
|
verbose: opts.verbose,
|
|
110515
|
-
loginCustomerId: opts.loginCustomerId
|
|
111014
|
+
loginCustomerId: opts.loginCustomerId,
|
|
111015
|
+
lang: opts.lang
|
|
110516
111016
|
});
|
|
110517
111017
|
}
|
|
110518
111018
|
);
|
|
@@ -110525,7 +111025,7 @@ function register11(program2) {
|
|
|
110525
111025
|
"--fallback-target-cpa <yuan>",
|
|
110526
111026
|
"\u7EC4\u65E0 targetCpa\uFF08\u6216\u521B\u610F\u7EF4\uFF09\u65F6\u4F7F\u7528\u7684\u76EE\u6807 CPA\uFF08\u5143\uFF09",
|
|
110527
111027
|
(v) => parseFloat(v)
|
|
110528
|
-
).option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF09", (v) => parseInt(v, 10)).option("--login-customer-id <id>", LOGIN_CUSTOMER_ID_OPTION_HELP).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--json-out <path>", "\u843D\u76D8\u76EE\u5F55\u6216 *.json", void 0).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF", false).action(
|
|
111028
|
+
).option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF09", (v) => parseInt(v, 10)).option("--login-customer-id <id>", LOGIN_CUSTOMER_ID_OPTION_HELP).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--json-out <path>", "\u843D\u76D8\u76EE\u5F55\u6216 *.json", void 0).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission", false).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF", false).option("--lang <lang>", "\u4EA4\u7ED9\u7528\u6237\u7684\u53E5\u5B50\u8BED\u8A00\uFF1Azh \u6216 en\uFF0C\u9ED8\u8BA4 zh").action(
|
|
110529
111029
|
async (opts) => {
|
|
110530
111030
|
await runZeroConv({
|
|
110531
111031
|
media: opts.media,
|
|
@@ -110540,7 +111040,8 @@ function register11(program2) {
|
|
|
110540
111040
|
jsonOut: opts.jsonOut,
|
|
110541
111041
|
refreshDp: opts.refreshDp,
|
|
110542
111042
|
verbose: opts.verbose,
|
|
110543
|
-
loginCustomerId: opts.loginCustomerId
|
|
111043
|
+
loginCustomerId: opts.loginCustomerId,
|
|
111044
|
+
lang: opts.lang
|
|
110544
111045
|
});
|
|
110545
111046
|
}
|
|
110546
111047
|
);
|
|
@@ -120853,6 +121354,19 @@ var LAYER_TITLE = {
|
|
|
120853
121354
|
negative_keyword: "\u5426\u5B9A\u8BCD",
|
|
120854
121355
|
extension: "\u9644\u52A0\u4FE1\u606F"
|
|
120855
121356
|
};
|
|
121357
|
+
var LAYER_TITLE_EN = {
|
|
121358
|
+
campaign: "Campaign",
|
|
121359
|
+
location: "Locations",
|
|
121360
|
+
excluded_location: "Excluded locations",
|
|
121361
|
+
adgroup: "Ad group",
|
|
121362
|
+
keyword: "Keywords",
|
|
121363
|
+
ad: "RSA copy",
|
|
121364
|
+
negative_keyword: "Negative keywords",
|
|
121365
|
+
extension: "Extensions"
|
|
121366
|
+
};
|
|
121367
|
+
function layerTitle(layer, lang) {
|
|
121368
|
+
return lang === "en" ? LAYER_TITLE_EN[layer] : LAYER_TITLE[layer];
|
|
121369
|
+
}
|
|
120856
121370
|
var STATUS_MARK = {
|
|
120857
121371
|
ok: "\u2705",
|
|
120858
121372
|
missing: "\u274C",
|
|
@@ -120893,53 +121407,59 @@ function printPlanItemsByAdGroup(configFile, layer, layerItems) {
|
|
|
120893
121407
|
function mdCell(text3) {
|
|
120894
121408
|
return text3.replace(/\r?\n/g, " ").replace(/\|/g, "\uFF5C").trim();
|
|
120895
121409
|
}
|
|
120896
|
-
function statusLabel(status) {
|
|
121410
|
+
function statusLabel(status, lang = "zh") {
|
|
121411
|
+
if (lang === "en") {
|
|
121412
|
+
if (status === "ok") return "\u2705 Created";
|
|
121413
|
+
if (status === "missing") return "\u274C Not created";
|
|
121414
|
+
return "\u23ED Not compared";
|
|
121415
|
+
}
|
|
120897
121416
|
if (status === "ok") return "\u2705 \u5DF2\u521B\u5EFA";
|
|
120898
121417
|
if (status === "missing") return "\u274C \u672A\u521B\u5EFA";
|
|
120899
121418
|
return "\u23ED \u672A\u6BD4\u5BF9";
|
|
120900
121419
|
}
|
|
120901
|
-
function buildCampaignCreateStatusMarkdown(result) {
|
|
121420
|
+
function buildCampaignCreateStatusMarkdown(result, lang = "zh") {
|
|
121421
|
+
const en = lang === "en";
|
|
120902
121422
|
const sc = result.statusCounts;
|
|
120903
121423
|
const c = result.counts;
|
|
120904
|
-
const conclusion = result.ok ? "\u2705 **\u5168\u90E8\u6210\u529F**\uFF1A\u8BA1\u5212\u5185\u5404\u9879\u5747\u5DF2\u5728\u8D26\u6237\u751F\u6548" : `\u274C **\u90E8\u5206\u5931\u8D25**\uFF1A\u4ECD\u6709 **${sc.missing}** \u9879\u672A\u521B\u5EFA\uFF08\u53E6\u6709 ${sc.skipped} \u9879\u56E0\u7236\u7EA7\u7F3A\u5931\u672A\u6BD4\u5BF9\uFF09`;
|
|
121424
|
+
const conclusion = result.ok ? en ? "\u2705 **All created**: every planned item is live on the account" : "\u2705 **\u5168\u90E8\u6210\u529F**\uFF1A\u8BA1\u5212\u5185\u5404\u9879\u5747\u5DF2\u5728\u8D26\u6237\u751F\u6548" : en ? `\u274C **Partly failed**: **${sc.missing}** items were not created (${sc.skipped} skipped because a parent is missing)` : `\u274C **\u90E8\u5206\u5931\u8D25**\uFF1A\u4ECD\u6709 **${sc.missing}** \u9879\u672A\u521B\u5EFA\uFF08\u53E6\u6709 ${sc.skipped} \u9879\u56E0\u7236\u7EA7\u7F3A\u5931\u672A\u6BD4\u5BF9\uFF09`;
|
|
120905
121425
|
const lines = [
|
|
120906
|
-
`# Google \u641C\u7D22\u5E7F\u544A\u521B\u5EFA\u8BE6\u60C5`,
|
|
121426
|
+
en ? `# Google Search campaign creation` : `# Google \u641C\u7D22\u5E7F\u544A\u521B\u5EFA\u8BE6\u60C5`,
|
|
120907
121427
|
``,
|
|
120908
|
-
`> \u672C\u6587\u6863\u7531 \`ad batch diff\` \u6839\u636E\u5E7F\u544A\u8BA1\u5212 JSON \u4E0E\u8D26\u6237\u5B9E\u51B5\u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6309\u8868\u683C\u6838\u5BF9\u6BCF\u6761\u6587\u6848/\u5173\u952E\u8BCD\u7684\u521B\u5EFA\u72B6\u6001\u3002`,
|
|
121428
|
+
en ? `> Generated by \`ad batch diff\` from the plan JSON and the live account. Check each keyword and RSA line in the tables.` : `> \u672C\u6587\u6863\u7531 \`ad batch diff\` \u6839\u636E\u5E7F\u544A\u8BA1\u5212 JSON \u4E0E\u8D26\u6237\u5B9E\u51B5\u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6309\u8868\u683C\u6838\u5BF9\u6BCF\u6761\u6587\u6848/\u5173\u952E\u8BCD\u7684\u521B\u5EFA\u72B6\u6001\u3002`,
|
|
120909
121429
|
``,
|
|
120910
|
-
`## \u6982\u89C8`,
|
|
121430
|
+
en ? `## Overview` : `## \u6982\u89C8`,
|
|
120911
121431
|
``,
|
|
120912
|
-
`| \u9879\u76EE | \u5185\u5BB9 |`,
|
|
121432
|
+
en ? `| Item | Value |` : `| \u9879\u76EE | \u5185\u5BB9 |`,
|
|
120913
121433
|
`| --- | --- |`,
|
|
120914
|
-
`| \u8D26\u6237 ID | \`${mdCell(result.accountId)}\` |`,
|
|
120915
|
-
`| \u7CFB\u5217\u540D\u79F0 | ${mdCell(result.campaignName || "\u2014")} |`,
|
|
120916
|
-
`| \u7CFB\u5217 ID (campaignId) | \`${mdCell(result.campaignId)}\` |`,
|
|
120917
|
-
`| \u6279\u91CF\u4EFB\u52A1 | ${mdCell(result.batchId || "\u2014")} / ${mdCell(result.batchStatus || "\u2014")} |`,
|
|
120918
|
-
`| \u8BA1\u5212\u914D\u7F6E | \`${mdCell(result.configFile || "\u2014")}\` |`,
|
|
120919
|
-
`| \u7ED3\u8BBA | ${conclusion} |`,
|
|
121434
|
+
en ? `| Account ID | \`${mdCell(result.accountId)}\` |` : `| \u8D26\u6237 ID | \`${mdCell(result.accountId)}\` |`,
|
|
121435
|
+
en ? `| Campaign | ${mdCell(result.campaignName || "\u2014")} |` : `| \u7CFB\u5217\u540D\u79F0 | ${mdCell(result.campaignName || "\u2014")} |`,
|
|
121436
|
+
en ? `| Campaign ID | \`${mdCell(result.campaignId)}\` |` : `| \u7CFB\u5217 ID (campaignId) | \`${mdCell(result.campaignId)}\` |`,
|
|
121437
|
+
en ? `| Batch | ${mdCell(result.batchId || "\u2014")} / ${mdCell(result.batchStatus || "\u2014")} |` : `| \u6279\u91CF\u4EFB\u52A1 | ${mdCell(result.batchId || "\u2014")} / ${mdCell(result.batchStatus || "\u2014")} |`,
|
|
121438
|
+
en ? `| Plan file | \`${mdCell(result.configFile || "\u2014")}\` |` : `| \u8BA1\u5212\u914D\u7F6E | \`${mdCell(result.configFile || "\u2014")}\` |`,
|
|
121439
|
+
en ? `| Result | ${conclusion} |` : `| \u7ED3\u8BBA | ${conclusion} |`,
|
|
120920
121440
|
``,
|
|
120921
|
-
`## \u6570\u91CF\u6C47\u603B`,
|
|
121441
|
+
en ? `## Counts` : `## \u6570\u91CF\u6C47\u603B`,
|
|
120922
121442
|
``,
|
|
120923
|
-
`| \u5C42\u7EA7 | \u8D26\u6237\u5B9E\u51B5 | \u8BA1\u5212 |`,
|
|
121443
|
+
en ? `| Layer | Live | Planned |` : `| \u5C42\u7EA7 | \u8D26\u6237\u5B9E\u51B5 | \u8BA1\u5212 |`,
|
|
120924
121444
|
`| --- | ---: | ---: |`,
|
|
120925
|
-
`|
|
|
120926
|
-
`|
|
|
120927
|
-
`|
|
|
120928
|
-
`|
|
|
120929
|
-
`|
|
|
120930
|
-
`|
|
|
120931
|
-
`|
|
|
121445
|
+
`| ${layerTitle("adgroup", lang)} | ${c.liveAdGroups} | ${c.plannedAdGroups} |`,
|
|
121446
|
+
`| ${layerTitle("keyword", lang)} | ${c.liveKeywords} | ${c.plannedKeywords} |`,
|
|
121447
|
+
`| ${layerTitle("ad", lang)} | ${c.liveAds} | ${c.plannedAds} |`,
|
|
121448
|
+
`| ${layerTitle("negative_keyword", lang)} | ${c.liveNegativeKeywords} | ${c.plannedNegativeKeywords} |`,
|
|
121449
|
+
`| ${layerTitle("extension", lang)} | ${c.liveExtensions} | ${c.plannedExtensions} |`,
|
|
121450
|
+
`| ${layerTitle("location", lang)} | ${c.liveLocations} | ${c.plannedLocations} |`,
|
|
121451
|
+
`| ${layerTitle("excluded_location", lang)} | ${c.liveExcludedLocations} | ${c.plannedExcludedLocations} |`,
|
|
120932
121452
|
``,
|
|
120933
|
-
`**\u9010\u9879\u72B6\u6001\u8BA1\u6570**\uFF1A\u2705 ${sc.ok}\u3000\u274C ${sc.missing}\u3000\u23ED ${sc.skipped}\u3000\u5408\u8BA1 ${result.items.length}`,
|
|
121453
|
+
en ? `**Status counts**: \u2705 ${sc.ok}\u3000\u274C ${sc.missing}\u3000\u23ED ${sc.skipped}\u3000total ${result.items.length}` : `**\u9010\u9879\u72B6\u6001\u8BA1\u6570**\uFF1A\u2705 ${sc.ok}\u3000\u274C ${sc.missing}\u3000\u23ED ${sc.skipped}\u3000\u5408\u8BA1 ${result.items.length}`,
|
|
120934
121454
|
``
|
|
120935
121455
|
];
|
|
120936
121456
|
const emptyInPlan = [
|
|
120937
|
-
c.plannedExcludedLocations === 0 ? "
|
|
120938
|
-
c.plannedNegativeKeywords === 0 ? "
|
|
121457
|
+
c.plannedExcludedLocations === 0 ? layerTitle("excluded_location", lang) : "",
|
|
121458
|
+
c.plannedNegativeKeywords === 0 ? layerTitle("negative_keyword", lang) : ""
|
|
120939
121459
|
].filter(Boolean);
|
|
120940
121460
|
if (emptyInPlan.length > 0) {
|
|
120941
121461
|
lines.push(
|
|
120942
|
-
`> \u26A0\uFE0F \u672C\u6B21\u63D0\u4EA4\u7684\u8BA1\u5212 JSON \u4E2D **${emptyInPlan.join("\u3001")}\u4E3A 0 \u6761**\uFF0C\u8D26\u6237\u5185\u4E5F\u5C31\u6CA1\u6709\u8BBE\u7F6E\u3002\u82E5\u6295\u653E\u65B9\u6848\u539F\u672C\u6709\u8FD9\u4E9B\u5185\u5BB9\uFF0C\u8BF4\u660E\u521B\u5EFA\u8FC7\u7A0B\u4E2D\u88AB\u79FB\u9664\uFF0C\u8BF7\u4E0E\u52A9\u624B\u6838\u5BF9\u662F\u5426\u9700\u8981\u8865\u4E0A\u3002`,
|
|
121462
|
+
en ? `> \u26A0\uFE0F The submitted plan JSON has **0 ${emptyInPlan.join(" and ")}**. The account has none either. If the brief included them, they were dropped during creation \u2014 ask the assistant to add them back.` : `> \u26A0\uFE0F \u672C\u6B21\u63D0\u4EA4\u7684\u8BA1\u5212 JSON \u4E2D **${emptyInPlan.join("\u3001")}\u4E3A 0 \u6761**\uFF0C\u8D26\u6237\u5185\u4E5F\u5C31\u6CA1\u6709\u8BBE\u7F6E\u3002\u82E5\u6295\u653E\u65B9\u6848\u539F\u672C\u6709\u8FD9\u4E9B\u5185\u5BB9\uFF0C\u8BF4\u660E\u521B\u5EFA\u8FC7\u7A0B\u4E2D\u88AB\u79FB\u9664\uFF0C\u8BF7\u4E0E\u52A9\u624B\u6838\u5BF9\u662F\u5426\u9700\u8981\u8865\u4E0A\u3002`,
|
|
120943
121463
|
``
|
|
120944
121464
|
);
|
|
120945
121465
|
}
|
|
@@ -120957,15 +121477,18 @@ function buildCampaignCreateStatusMarkdown(result) {
|
|
|
120957
121477
|
}
|
|
120958
121478
|
for (const [groupName, groupItems] of byGroup) {
|
|
120959
121479
|
if (layer === "keyword") {
|
|
120960
|
-
lines.push(
|
|
120961
|
-
|
|
121480
|
+
lines.push(
|
|
121481
|
+
en ? `## Ad group \u201C${groupName}\u201D \xB7 Keywords` : `## \u5E7F\u544A\u7EC4\u300C${groupName}\u300D\xB7 \u5173\u952E\u8BCD`,
|
|
121482
|
+
``
|
|
121483
|
+
);
|
|
121484
|
+
lines.push(en ? `| Status | Planned |` : `| \u72B6\u6001 | \u8BA1\u5212\u5185\u5BB9 |`, `| --- | --- |`);
|
|
120962
121485
|
for (const item of groupItems) {
|
|
120963
|
-
lines.push(`| ${statusLabel(item.status)} | ${mdCell(item.plannedContent)} |`);
|
|
121486
|
+
lines.push(`| ${statusLabel(item.status, lang)} | ${mdCell(item.plannedContent)} |`);
|
|
120964
121487
|
}
|
|
120965
121488
|
lines.push(``);
|
|
120966
121489
|
continue;
|
|
120967
121490
|
}
|
|
120968
|
-
lines.push(`## \u5E7F\u544A\u7EC4\u300C${groupName}\u300D\xB7 RSA \u6587\u6848`, ``);
|
|
121491
|
+
lines.push(en ? `## Ad group \u201C${groupName}\u201D \xB7 RSA` : `## \u5E7F\u544A\u7EC4\u300C${groupName}\u300D\xB7 RSA \u6587\u6848`, ``);
|
|
120969
121492
|
const byAd = /* @__PURE__ */ new Map();
|
|
120970
121493
|
for (const item of groupItems) {
|
|
120971
121494
|
const key = item.adLabel ?? "\u2014";
|
|
@@ -120974,39 +121497,47 @@ function buildCampaignCreateStatusMarkdown(result) {
|
|
|
120974
121497
|
byAd.set(key, list);
|
|
120975
121498
|
}
|
|
120976
121499
|
for (const [adLabel, adItems] of byAd) {
|
|
120977
|
-
lines.push(`### \u5E7F\u544A\u300C${adLabel}\u300D`, ``);
|
|
120978
|
-
lines.push(`| \u72B6\u6001 | \u8BA1\u5212\u5185\u5BB9 |`, `| --- | --- |`);
|
|
121500
|
+
lines.push(en ? `### Ad \u201C${adLabel}\u201D` : `### \u5E7F\u544A\u300C${adLabel}\u300D`, ``);
|
|
121501
|
+
lines.push(en ? `| Status | Planned |` : `| \u72B6\u6001 | \u8BA1\u5212\u5185\u5BB9 |`, `| --- | --- |`);
|
|
120979
121502
|
for (const item of adItems) {
|
|
120980
|
-
lines.push(`| ${statusLabel(item.status)} | ${mdCell(item.plannedContent)} |`);
|
|
121503
|
+
lines.push(`| ${statusLabel(item.status, lang)} | ${mdCell(item.plannedContent)} |`);
|
|
120981
121504
|
}
|
|
120982
121505
|
lines.push(``);
|
|
120983
121506
|
}
|
|
120984
121507
|
}
|
|
120985
121508
|
continue;
|
|
120986
121509
|
}
|
|
120987
|
-
lines.push(`## ${
|
|
120988
|
-
lines.push(`| \u72B6\u6001 | \u8BA1\u5212\u5185\u5BB9 |`, `| --- | --- |`);
|
|
121510
|
+
lines.push(`## ${layerTitle(layer, lang)}`, ``);
|
|
121511
|
+
lines.push(en ? `| Status | Planned |` : `| \u72B6\u6001 | \u8BA1\u5212\u5185\u5BB9 |`, `| --- | --- |`);
|
|
120989
121512
|
for (const item of layerItems) {
|
|
120990
|
-
lines.push(`| ${statusLabel(item.status)} | ${mdCell(item.plannedContent)} |`);
|
|
121513
|
+
lines.push(`| ${statusLabel(item.status, lang)} | ${mdCell(item.plannedContent)} |`);
|
|
120991
121514
|
}
|
|
120992
121515
|
lines.push(``);
|
|
120993
121516
|
}
|
|
120994
121517
|
if (result.missing.length > 0) {
|
|
120995
|
-
lines.push(`## \u4ECD\u672A\u521B\u5EFA\u9879\uFF08\u987B\u5173\u6CE8\uFF09`, ``);
|
|
120996
|
-
lines.push(
|
|
121518
|
+
lines.push(en ? `## Still missing (needs attention)` : `## \u4ECD\u672A\u521B\u5EFA\u9879\uFF08\u987B\u5173\u6CE8\uFF09`, ``);
|
|
121519
|
+
lines.push(
|
|
121520
|
+
en ? `| Layer | Planned | Note |` : `| \u5C42\u7EA7 | \u8BA1\u5212\u5185\u5BB9 | \u8BF4\u660E |`,
|
|
121521
|
+
`| --- | --- | --- |`
|
|
121522
|
+
);
|
|
120997
121523
|
for (const m of result.missing) {
|
|
120998
121524
|
lines.push(
|
|
120999
|
-
`| ${
|
|
121525
|
+
`| ${layerTitle(m.layer, lang)} | ${mdCell(m.plannedContent)} | ${mdCell(m.summary)} |`
|
|
121000
121526
|
);
|
|
121001
121527
|
}
|
|
121002
121528
|
lines.push(``);
|
|
121003
121529
|
} else {
|
|
121004
|
-
lines.push(
|
|
121530
|
+
lines.push(
|
|
121531
|
+
en ? `## Still missing` : `## \u4ECD\u672A\u521B\u5EFA\u9879`,
|
|
121532
|
+
``,
|
|
121533
|
+
en ? `None. The plan matches the live account.` : `\u65E0\u3002\u8BA1\u5212\u4E0E\u8D26\u6237\u5B9E\u51B5\u4E00\u81F4\u3002`,
|
|
121534
|
+
``
|
|
121535
|
+
);
|
|
121005
121536
|
}
|
|
121006
121537
|
lines.push(
|
|
121007
|
-
`## \u8BF4\u660E`,
|
|
121538
|
+
en ? `## Notes` : `## \u8BF4\u660E`,
|
|
121008
121539
|
``,
|
|
121009
|
-
result.ok ? `\u672C\u7CFB\u5217\u5DF2\u6309\u5E7F\u544A\u8BA1\u5212\u521B\u5EFA\u5B8C\u6210\u3002\u4E0A\u65B9\u8868\u683C\u5217\u51FA\u4E86\u6BCF\u4E00\u6761\u5173\u952E\u8BCD\u4E0E RSA \u6807\u9898/\u63CF\u8FF0\u7684\u751F\u6548\u72B6\u6001\uFF0C\u4FBF\u4E8E\u6838\u5BF9\u3002` : `\u672C\u7CFB\u5217\u5DF2\u90E8\u5206\u521B\u5EFA\u3002\u8BF7\u91CD\u70B9\u67E5\u770B\u300C\u4ECD\u672A\u521B\u5EFA\u9879\u300D\u4E0E\u8868\u683C\u4E2D\u7684 \u274C \u884C\uFF1B\u5982\u9700\u8865\u9F50\u7F3A\u5931\u5185\u5BB9\uFF0C\u53EF\u544A\u77E5\u52A9\u624B\u7EE7\u7EED\u5904\u7406\u3002`,
|
|
121540
|
+
result.ok ? en ? `This campaign matches the plan. The tables above show each keyword and RSA headline or description.` : `\u672C\u7CFB\u5217\u5DF2\u6309\u5E7F\u544A\u8BA1\u5212\u521B\u5EFA\u5B8C\u6210\u3002\u4E0A\u65B9\u8868\u683C\u5217\u51FA\u4E86\u6BCF\u4E00\u6761\u5173\u952E\u8BCD\u4E0E RSA \u6807\u9898/\u63CF\u8FF0\u7684\u751F\u6548\u72B6\u6001\uFF0C\u4FBF\u4E8E\u6838\u5BF9\u3002` : en ? `This campaign is only partly created. Check \u201CStill missing\u201D and the \u274C rows. Ask the assistant to fill the gaps.` : `\u672C\u7CFB\u5217\u5DF2\u90E8\u5206\u521B\u5EFA\u3002\u8BF7\u91CD\u70B9\u67E5\u770B\u300C\u4ECD\u672A\u521B\u5EFA\u9879\u300D\u4E0E\u8868\u683C\u4E2D\u7684 \u274C \u884C\uFF1B\u5982\u9700\u8865\u9F50\u7F3A\u5931\u5185\u5BB9\uFF0C\u53EF\u544A\u77E5\u52A9\u624B\u7EE7\u7EED\u5904\u7406\u3002`,
|
|
121010
121541
|
``
|
|
121011
121542
|
);
|
|
121012
121543
|
return lines.join("\n");
|
|
@@ -121025,8 +121556,8 @@ function resolveBatchDiffMdOutPath(opts) {
|
|
|
121025
121556
|
}
|
|
121026
121557
|
return path15.resolve(fileName);
|
|
121027
121558
|
}
|
|
121028
|
-
function writeCampaignCreateStatusMarkdown(result, mdPath) {
|
|
121029
|
-
const reportMarkdown = buildCampaignCreateStatusMarkdown(result);
|
|
121559
|
+
function writeCampaignCreateStatusMarkdown(result, mdPath, lang = "zh") {
|
|
121560
|
+
const reportMarkdown = buildCampaignCreateStatusMarkdown(result, lang);
|
|
121030
121561
|
fs10.mkdirSync(path15.dirname(mdPath), { recursive: true });
|
|
121031
121562
|
fs10.writeFileSync(mdPath, reportMarkdown, "utf8");
|
|
121032
121563
|
return { reportMarkdown, reportMarkdownFile: mdPath };
|
|
@@ -121194,7 +121725,7 @@ async function runCampaignBatchDiff(opts) {
|
|
|
121194
121725
|
jsonOut: opts.jsonOut,
|
|
121195
121726
|
campaignId
|
|
121196
121727
|
});
|
|
121197
|
-
const report = writeCampaignCreateStatusMarkdown(result, mdPath);
|
|
121728
|
+
const report = writeCampaignCreateStatusMarkdown(result, mdPath, opts.lang === "en" ? "en" : "zh");
|
|
121198
121729
|
const payload = {
|
|
121199
121730
|
...result,
|
|
121200
121731
|
...report
|
|
@@ -124880,6 +125411,9 @@ PMax \u5730\u7406\u62A5\u8868\uFF08\u6D3B\u52A8\xD7\u56FD\u5BB6\uFF0C${query.get
|
|
|
124880
125411
|
});
|
|
124881
125412
|
}
|
|
124882
125413
|
|
|
125414
|
+
// src/commands/ad/_register.ts
|
|
125415
|
+
init_lang();
|
|
125416
|
+
|
|
124883
125417
|
// src/commands/ad/campaign-validate.ts
|
|
124884
125418
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
124885
125419
|
init_cli_json_snapshot();
|
|
@@ -125248,7 +125782,7 @@ function register21(program2) {
|
|
|
125248
125782
|
).option("--batch-id <id>", "\u6279\u91CF\u4EFB\u52A1 ID\uFF08\u6821\u9A8C\u975E Failed\uFF1BHasFailed \u65F6\u53EF\u7701\u7565 campaign-id\uFF09").option("-a, --account <id>", "\u5A92\u4F53\u8D26\u6237 ID\uFF08\u9ED8\u8BA4\u8BFB JSON \u7684 account\uFF09").option("--json-out <path>", "\u6BD4\u5BF9\u7ED3\u679C\u843D\u76D8\u8DEF\u5F84\uFF08\u542B reportMarkdown\uFF09").option(
|
|
125249
125783
|
"--md-out <path>",
|
|
125250
125784
|
"\u521B\u5EFA\u8BE6\u60C5 Markdown \u843D\u76D8\u8DEF\u5F84\uFF08\u9ED8\u8BA4\uFF1A\u4E0E --json-out \u540C\u76EE\u5F55\u7684 campaign-create-status-<campaignId>.md\uFF09"
|
|
125251
|
-
).option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
125785
|
+
).option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).option("--lang <lang>", "\u4EA4\u7ED9\u7528\u6237\u7684\u521B\u5EFA\u8BE6\u60C5\u8BED\u8A00\uFF1Azh \u6216 en\uFF0C\u9ED8\u8BA4 zh").action(
|
|
125252
125786
|
async (opts) => {
|
|
125253
125787
|
await runCampaignBatchDiff({
|
|
125254
125788
|
token: opts.token,
|
|
@@ -125258,7 +125792,8 @@ function register21(program2) {
|
|
|
125258
125792
|
account: opts.account,
|
|
125259
125793
|
jsonOut: opts.jsonOut,
|
|
125260
125794
|
mdOut: opts.mdOut,
|
|
125261
|
-
verbose: opts.verbose
|
|
125795
|
+
verbose: opts.verbose,
|
|
125796
|
+
lang: readReportLangOrExit({ flag: opts.lang })
|
|
125262
125797
|
});
|
|
125263
125798
|
}
|
|
125264
125799
|
);
|
|
@@ -128015,6 +128550,8 @@ async function runMetaAdFormCreate(opts) {
|
|
|
128015
128550
|
init_xlsx_style_engine();
|
|
128016
128551
|
import fs12 from "fs";
|
|
128017
128552
|
import path17 from "path";
|
|
128553
|
+
init_html();
|
|
128554
|
+
init_lang();
|
|
128018
128555
|
var PENDING = "[\u5F85\u8865]";
|
|
128019
128556
|
var SHEET_NAMES = ["\u65B9\u6848\u603B\u89C8", "1-\u5BA2\u6237\u753B\u50CF", "2-\u8D26\u6237\u7ED3\u6784", "3-\u8868\u5355\u8BE2\u76D8C1"];
|
|
128020
128557
|
var OPS = {
|
|
@@ -128035,6 +128572,9 @@ var QUESTION_TYPE_LABEL = {
|
|
|
128035
128572
|
JOB_TITLE: "Job Title",
|
|
128036
128573
|
CUSTOM: "Custom"
|
|
128037
128574
|
};
|
|
128575
|
+
function chrome(text3, lang) {
|
|
128576
|
+
return lang === "en" ? applyEnglishPhrases(text3) : text3;
|
|
128577
|
+
}
|
|
128038
128578
|
function text2(value) {
|
|
128039
128579
|
if (value == null) return PENDING;
|
|
128040
128580
|
const s = String(value).trim();
|
|
@@ -128149,12 +128689,13 @@ function resolveCopyBlocks(cfg) {
|
|
|
128149
128689
|
}
|
|
128150
128690
|
return blocks;
|
|
128151
128691
|
}
|
|
128152
|
-
function writeOpsExcel(outPath, cfg) {
|
|
128692
|
+
function writeOpsExcel(outPath, cfg, lang = "zh") {
|
|
128153
128693
|
const plan = cfg.plan ?? {};
|
|
128154
128694
|
const wb = createExcelWorkbook({ accent: "1F4E79" });
|
|
128155
128695
|
const adSets = resolveAdSets(cfg);
|
|
128156
128696
|
const subtitle = defaultSubtitle(cfg);
|
|
128157
|
-
const
|
|
128697
|
+
const sheet = (index) => chrome(SHEET_NAMES[index], lang);
|
|
128698
|
+
const overview = wb.addSheet(sheet(0));
|
|
128158
128699
|
overview.setColWidths([20, 18, 18, 18, 18, 42]);
|
|
128159
128700
|
overview.titleBar(overviewTitle(plan), {
|
|
128160
128701
|
fill: null,
|
|
@@ -128163,22 +128704,22 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128163
128704
|
hAlign: "center"
|
|
128164
128705
|
});
|
|
128165
128706
|
overview.blankRow();
|
|
128166
|
-
overview.kvRow("\u5BA2\u6237\u540D\u79F0", text2(plan.customerName));
|
|
128167
|
-
overview.kvRow("Facebook \u4E3B\u9875", text2(plan.pageUrl || "\u5F85 pages \u540E\u8865"), {
|
|
128707
|
+
overview.kvRow(chrome("\u5BA2\u6237\u540D\u79F0", lang), text2(plan.customerName));
|
|
128708
|
+
overview.kvRow(chrome("Facebook \u4E3B\u9875", lang), text2(plan.pageUrl || chrome("\u5F85 pages \u540E\u8865", lang)), {
|
|
128168
128709
|
hyperlink: plan.pageUrl?.startsWith("http") ? plan.pageUrl : void 0
|
|
128169
128710
|
});
|
|
128170
|
-
overview.kvRow("\u5B98\u65B9\u7F51\u7AD9", text2(plan.siteUrl), {
|
|
128711
|
+
overview.kvRow(chrome("\u5B98\u65B9\u7F51\u7AD9", lang), text2(plan.siteUrl), {
|
|
128171
128712
|
hyperlink: plan.siteUrl?.startsWith("http") ? plan.siteUrl : void 0
|
|
128172
128713
|
});
|
|
128173
|
-
overview.kvRow("\u4E3B\u8425\u4E1A\u52A1", text2(plan.businessOneLiner));
|
|
128174
|
-
overview.kvRow("\u6838\u5FC3\u4EA7\u54C1", text2(plan.products));
|
|
128175
|
-
overview.kvRow("\u6838\u5FC3\u5356\u70B9", text2(plan.sellingPoints));
|
|
128176
|
-
overview.kvRow("\u76EE\u6807\u5E02\u573A", text2(plan.targetMarkets || joinList(cfg.adset?.countries, ", ")));
|
|
128177
|
-
overview.kvRow("\u8425\u9500\u76EE\u6807", text2(plan.mainResult || "\u8868\u5355\u8BE2\u76D8\uFF08Lead Form\uFF09"));
|
|
128178
|
-
overview.kvRow("\u65E5\u9884\u7B97", dailyBudgetText(cfg));
|
|
128179
|
-
overview.kvRow("\u5E7F\u544A\u7ED3\u6784", structureSummary(cfg));
|
|
128180
|
-
overview.kvRow("\u6295\u653E\u7B56\u7565", text2(plan.strategy || plan.landingType));
|
|
128181
|
-
const profile = wb.addSheet(
|
|
128714
|
+
overview.kvRow(chrome("\u4E3B\u8425\u4E1A\u52A1", lang), text2(plan.businessOneLiner));
|
|
128715
|
+
overview.kvRow(chrome("\u6838\u5FC3\u4EA7\u54C1", lang), text2(plan.products));
|
|
128716
|
+
overview.kvRow(chrome("\u6838\u5FC3\u5356\u70B9", lang), text2(plan.sellingPoints));
|
|
128717
|
+
overview.kvRow(chrome("\u76EE\u6807\u5E02\u573A", lang), text2(plan.targetMarkets || joinList(cfg.adset?.countries, ", ")));
|
|
128718
|
+
overview.kvRow(chrome("\u8425\u9500\u76EE\u6807", lang), text2(plan.mainResult || chrome("\u8868\u5355\u8BE2\u76D8\uFF08Lead Form\uFF09", lang)));
|
|
128719
|
+
overview.kvRow(chrome("\u65E5\u9884\u7B97", lang), dailyBudgetText(cfg));
|
|
128720
|
+
overview.kvRow(chrome("\u5E7F\u544A\u7ED3\u6784", lang), structureSummary(cfg));
|
|
128721
|
+
overview.kvRow(chrome("\u6295\u653E\u7B56\u7565", lang), text2(plan.strategy || plan.landingType));
|
|
128722
|
+
const profile = wb.addSheet(sheet(1));
|
|
128182
128723
|
profile.setColWidths([26, 48, 26, 26]);
|
|
128183
128724
|
profile.titleBar(profileTitle(plan), { fill: OPS.title });
|
|
128184
128725
|
profile.subtitleBar(subtitle);
|
|
@@ -128220,7 +128761,7 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128220
128761
|
profile.noteRow(
|
|
128221
128762
|
plan.targeting?.disclaimer?.trim() || "\u672C\u6279\u7EC4\u5B9A\u5411\u53EA\u8BA4\u56FD\u5BB6/\u5E74\u9F84/\u6027\u522B\uFF0C\u5174\u8DA3\u8BCD\u4EC5\u4F5C\u7D20\u6750\u4E0E\u83B7\u5BA2\u8BF4\u660E"
|
|
128222
128763
|
);
|
|
128223
|
-
const structure = wb.addSheet(
|
|
128764
|
+
const structure = wb.addSheet(sheet(2));
|
|
128224
128765
|
structure.setColWidths([18, 44, 26, 22]);
|
|
128225
128766
|
structure.titleBar(text2(plan.brand ? `\u5E7F\u544A\u8D26\u6237\u7ED3\u6784\uFF1A${plan.brand}` : "\u5E7F\u544A\u8D26\u6237\u7ED3\u6784"), {
|
|
128226
128767
|
fill: OPS.title
|
|
@@ -128259,7 +128800,7 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128259
128800
|
structure.noteRow(
|
|
128260
128801
|
plan.structureNote?.trim() || `\u8BF4\u660E\uFF1AC1 \u8868\u5355\u8BE2\u76D8\u8BA1\u5212 ${adSets.length} \u7EC4\uFF1B\u672C\u6B21 create \u53EA\u843D\u5730 1 \u7CFB\u5217 \xD7 1 \u7EC4 \xD7 1 \u521B\u610F \xD7 1 \u5E7F\u544A\uFF0C\u5176\u4F59\u786E\u8BA4\u540E\u7528\u539F\u8BED\u7EED\u5EFA\u3002`
|
|
128261
128802
|
);
|
|
128262
|
-
const lead = wb.addSheet(
|
|
128803
|
+
const lead = wb.addSheet(sheet(3));
|
|
128263
128804
|
lead.setColWidths([16, 22, 36, 40, 16, 18]);
|
|
128264
128805
|
lead.titleBar(`Campaign 1\uFF1A\u8868\u5355\u8BE2\u76D8\uFF08Leads\uFF09\uFF5C ${dailyBudgetText(cfg)}`, { fill: OPS.title });
|
|
128265
128806
|
lead.subtitleBar(subtitle);
|
|
@@ -128313,7 +128854,7 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128313
128854
|
}
|
|
128314
128855
|
return wb.writeFile(outPath);
|
|
128315
128856
|
}
|
|
128316
|
-
function renderMarkdown(cfg) {
|
|
128857
|
+
function renderMarkdown(cfg, lang = "zh") {
|
|
128317
128858
|
const plan = cfg.plan ?? {};
|
|
128318
128859
|
const adSets = resolveAdSets(cfg);
|
|
128319
128860
|
const questions = (cfg.form?.questions ?? []).map(
|
|
@@ -128325,13 +128866,14 @@ function renderMarkdown(cfg) {
|
|
|
128325
128866
|
|
|
128326
128867
|
${text2(block.text)}
|
|
128327
128868
|
`).join("\n");
|
|
128869
|
+
const h = (label2) => chrome(label2, lang);
|
|
128328
128870
|
return `# ${overviewTitle(plan)}
|
|
128329
128871
|
|
|
128330
|
-
- \u5BA2\u6237
|
|
128331
|
-
- \
|
|
128872
|
+
- ${h("\u5BA2\u6237\u540D\u79F0")}/${h("\u5B98\u65B9\u7F51\u7AD9")}\uFF1A${text2(plan.customerName)} + ${text2(plan.siteUrl)} + ${text2(plan.businessOneLiner)}
|
|
128873
|
+
- ${h("\u8425\u9500\u76EE\u6807")}\uFF1A${text2(plan.mainResult)}
|
|
128332
128874
|
- \u843D\u5730\u5EFA\u8BAE\uFF1A${text2(plan.landingType)}
|
|
128333
|
-
- \u65E5\u9884\u7B97\uFF1A${dailyBudgetText(cfg)}\u3000\u56FD\u5BB6\uFF1A${joinList(cfg.adset?.countries, ", ")}
|
|
128334
|
-
- \u5E7F\u544A\u7ED3\u6784\uFF1A${structureSummary(cfg)}
|
|
128875
|
+
- ${h("\u65E5\u9884\u7B97")}\uFF1A${dailyBudgetText(cfg)}\u3000${h("\u56FD\u5BB6")}\uFF1A${joinList(cfg.adset?.countries, ", ")}
|
|
128876
|
+
- ${h("\u5E7F\u544A\u7ED3\u6784")}\uFF1A${structureSummary(cfg)}
|
|
128335
128877
|
- \u8BA1\u5212\u72B6\u6001\uFF1A**\u5F85\u786E\u8BA4**\u3000\u672C\u6279\u53EF\u6267\u884C\uFF1AInstant Form \u7EBF\u7D22\u5E7F\u544A\uFF08\u975E Advantage+\uFF09
|
|
128336
128878
|
|
|
128337
128879
|
> \u8D26\u6237\uFF1A${text2(cfg.account)}\u3000\u4E3B\u9875\uFF1A${text2(cfg.pageId)}
|
|
@@ -128391,24 +128933,25 @@ ${copies}
|
|
|
128391
128933
|
\u8349\u6848\u4F9D\u636E\u4E3A\u516C\u5F00\u9875\u9762/\u5BA2\u6237\u6750\u6599\uFF0C\u975E\u5E7F\u544A\u540E\u53F0\u6570\u636E\u3002
|
|
128392
128934
|
`;
|
|
128393
128935
|
}
|
|
128394
|
-
function writeMetaLeadPlanExcel(outPath, cfg) {
|
|
128395
|
-
return writeOpsExcel(outPath, cfg);
|
|
128936
|
+
function writeMetaLeadPlanExcel(outPath, cfg, lang = "zh") {
|
|
128937
|
+
return writeOpsExcel(outPath, cfg, lang);
|
|
128396
128938
|
}
|
|
128397
|
-
function writeMetaLeadPlanMarkdown(outPath, cfg) {
|
|
128939
|
+
function writeMetaLeadPlanMarkdown(outPath, cfg, lang = "zh") {
|
|
128398
128940
|
const abs = path17.resolve(outPath);
|
|
128399
128941
|
fs12.mkdirSync(path17.dirname(abs), { recursive: true });
|
|
128400
|
-
fs12.writeFileSync(abs, renderMarkdown(cfg), "utf8");
|
|
128942
|
+
fs12.writeFileSync(abs, renderMarkdown(cfg, lang), "utf8");
|
|
128401
128943
|
return abs;
|
|
128402
128944
|
}
|
|
128403
128945
|
async function runMetaAdPlanRender(opts) {
|
|
128404
128946
|
const cfg = loadMetaLeadCreateConfig(opts.configFile);
|
|
128947
|
+
const lang = readReportLangOrExit({ flag: opts.lang });
|
|
128405
128948
|
const configDir = path17.dirname(path17.resolve(opts.configFile));
|
|
128406
128949
|
const xlsxOut = path17.resolve(opts.out || path17.join(configDir, "meta-lead-plan.xlsx"));
|
|
128407
128950
|
const mdOut = path17.resolve(
|
|
128408
128951
|
opts.mdOut || path17.join(path17.dirname(xlsxOut), `${path17.parse(xlsxOut).name}.md`)
|
|
128409
128952
|
);
|
|
128410
|
-
const xlsxPath = writeMetaLeadPlanExcel(xlsxOut, cfg);
|
|
128411
|
-
const mdPath = writeMetaLeadPlanMarkdown(mdOut, cfg);
|
|
128953
|
+
const xlsxPath = writeMetaLeadPlanExcel(xlsxOut, cfg, lang);
|
|
128954
|
+
const mdPath = writeMetaLeadPlanMarkdown(mdOut, cfg, lang);
|
|
128412
128955
|
console.log(
|
|
128413
128956
|
JSON.stringify({
|
|
128414
128957
|
ok: true,
|
|
@@ -129196,7 +129739,7 @@ function register22(program2) {
|
|
|
129196
129739
|
await runMetaAdCreate(opts);
|
|
129197
129740
|
}
|
|
129198
129741
|
);
|
|
129199
|
-
meta.command("plan-render").description("\u6309\u8FD0\u8425\u56FA\u5B9A 4 Sheet \u6295\u5F71 Facebook \u7EBF\u7D22\u65B9\u6848 Excel + Markdown\uFF08\u4E0D\u8C03\u7F51\u5173\uFF1B\u7248\u5F0F\u9501\u6B7B\uFF09").requiredOption("--config-file <path>", "meta-lead-create JSON").option("--out <file>", "xlsx \u8F93\u51FA\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u4E0E JSON \u540C\u76EE\u5F55 meta-lead-plan.xlsx\uFF09").option("--md-out <file>", "Markdown \u5BA1\u67E5\u7A3F\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u4E0E xlsx \u540C\u540D .md\uFF09").action(async (opts) => {
|
|
129742
|
+
meta.command("plan-render").description("\u6309\u8FD0\u8425\u56FA\u5B9A 4 Sheet \u6295\u5F71 Facebook \u7EBF\u7D22\u65B9\u6848 Excel + Markdown\uFF08\u4E0D\u8C03\u7F51\u5173\uFF1B\u7248\u5F0F\u9501\u6B7B\uFF09").requiredOption("--config-file <path>", "meta-lead-create JSON").option("--out <file>", "xlsx \u8F93\u51FA\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u4E0E JSON \u540C\u76EE\u5F55 meta-lead-plan.xlsx\uFF09").option("--md-out <file>", "Markdown \u5BA1\u67E5\u7A3F\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u4E0E xlsx \u540C\u540D .md\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u9ED8\u8BA4\u4E2D\u6587").action(async (opts) => {
|
|
129200
129743
|
await runMetaAdPlanRender(opts);
|
|
129201
129744
|
});
|
|
129202
129745
|
addCommon(addAccount(meta.command("account").description("\u8BFB\u5E7F\u544A\u8D26\u6237\uFF08\u4F59\u989D/\u82B1\u8D39/\u5E01\u79CD\uFF09"))).action(
|
|
@@ -134470,6 +135013,8 @@ async function runWebsiteDiagnosisPrepare(opts) {
|
|
|
134470
135013
|
}
|
|
134471
135014
|
|
|
134472
135015
|
// src/commands/website-diagnosis/render-report.ts
|
|
135016
|
+
init_lang();
|
|
135017
|
+
init_html();
|
|
134473
135018
|
import fs16 from "fs";
|
|
134474
135019
|
import fsPromises from "fs/promises";
|
|
134475
135020
|
import path21 from "path";
|
|
@@ -134521,13 +135066,14 @@ function mergeCollectLighthouse(data, collect) {
|
|
|
134521
135066
|
...collect.lighthouseWarning && !data.lighthouseWarning ? { lighthouseWarning: collect.lighthouseWarning } : {}
|
|
134522
135067
|
};
|
|
134523
135068
|
}
|
|
134524
|
-
function injectReportData(html, payload) {
|
|
134525
|
-
const
|
|
135069
|
+
function injectReportData(html, payload, lang) {
|
|
135070
|
+
const localized = localizeReportHtml(html, lang);
|
|
135071
|
+
const json = JSON.stringify(stampMetaLang(payload, lang)).replace(/</g, "\\u003c");
|
|
134526
135072
|
const marker = "window.__WEBSITE_DIAGNOSIS__ = window.__WEBSITE_DIAGNOSIS__ || null;";
|
|
134527
|
-
if (!
|
|
135073
|
+
if (!localized.includes(marker)) {
|
|
134528
135074
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 website-diagnosis-report.html");
|
|
134529
135075
|
}
|
|
134530
|
-
return
|
|
135076
|
+
return localized.replace(marker, `window.__WEBSITE_DIAGNOSIS__ = ${json};`);
|
|
134531
135077
|
}
|
|
134532
135078
|
async function runWebsiteDiagnosisRender(opts) {
|
|
134533
135079
|
const dataPath = path21.resolve(opts.dataFile);
|
|
@@ -134537,6 +135083,7 @@ async function runWebsiteDiagnosisRender(opts) {
|
|
|
134537
135083
|
const collectRaw = await readJsonFile(path21.resolve(opts.collectFile));
|
|
134538
135084
|
data = mergeCollectLighthouse(data, asRecord5(collectRaw));
|
|
134539
135085
|
}
|
|
135086
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
134540
135087
|
const templatePath = websiteDiagnosisReportTemplatePath();
|
|
134541
135088
|
let html;
|
|
134542
135089
|
try {
|
|
@@ -134553,7 +135100,7 @@ async function runWebsiteDiagnosisRender(opts) {
|
|
|
134553
135100
|
);
|
|
134554
135101
|
const outDir = path21.dirname(outPath);
|
|
134555
135102
|
await fsPromises.mkdir(outDir, { recursive: true });
|
|
134556
|
-
await fsPromises.writeFile(outPath, injectReportData(html, data), "utf8");
|
|
135103
|
+
await fsPromises.writeFile(outPath, injectReportData(html, data, lang), "utf8");
|
|
134557
135104
|
const runtimeSrc = websiteDiagnosisRuntimePath();
|
|
134558
135105
|
const runtimeOut = path21.join(outDir, TEMPLATE_BASENAMES.runtime);
|
|
134559
135106
|
let runtimeCopied = false;
|
|
@@ -134620,11 +135167,12 @@ function registerWebsiteDiagnosisCommands(program2) {
|
|
|
134620
135167
|
jsonOut: opts.jsonOut
|
|
134621
135168
|
});
|
|
134622
135169
|
});
|
|
134623
|
-
root.command("render").description("\u6839\u636E\u8BCA\u65AD JSON \u751F\u6210 HTML \u7EC8\u7A3F\uFF08\u9ED8\u8BA4\u4EA4\u4ED8\u683C\u5F0F\uFF0Cwebsite-diagnosis-report.html\uFF09").requiredOption("--data <file>", "\u8BCA\u65AD\u7ED3\u679C JSON\uFF08getWebsiteDiagnosisData \u540C\u7ED3\u6784\uFF09").option("--collect <file>", "\u53EF\u9009\uFF1Acollect \u843D\u76D8 JSON\uFF0C\u7528\u4E8E\u5408\u5E76 lighthouse").option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
135170
|
+
root.command("render").description("\u6839\u636E\u8BCA\u65AD JSON \u751F\u6210 HTML \u7EC8\u7A3F\uFF08\u9ED8\u8BA4\u4EA4\u4ED8\u683C\u5F0F\uFF0Cwebsite-diagnosis-report.html\uFF09").requiredOption("--data <file>", "\u8BCA\u65AD\u7ED3\u679C JSON\uFF08getWebsiteDiagnosisData \u540C\u7ED3\u6784\uFF09").option("--collect <file>", "\u53EF\u9009\uFF1Acollect \u843D\u76D8 JSON\uFF0C\u7528\u4E8E\u5408\u5E76 lighthouse").option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
134624
135171
|
await runWebsiteDiagnosisRender({
|
|
134625
135172
|
dataFile: opts.data,
|
|
134626
135173
|
collectFile: opts.collect,
|
|
134627
|
-
out: opts.out
|
|
135174
|
+
out: opts.out,
|
|
135175
|
+
lang: opts.lang
|
|
134628
135176
|
});
|
|
134629
135177
|
});
|
|
134630
135178
|
}
|
|
@@ -134980,12 +135528,12 @@ function countTableColumns(tableHtml) {
|
|
|
134980
135528
|
return Math.max(th, td);
|
|
134981
135529
|
}
|
|
134982
135530
|
function isCompareTable(tableHtml, html, tableIndex) {
|
|
134983
|
-
const inTable =
|
|
135531
|
+
const inTable = /对比|竞品|功能|性能|维度|指标|参数|competitor|compare|feature/i.test(tableHtml);
|
|
134984
135532
|
if (inTable) return true;
|
|
134985
135533
|
const windowStart = Math.max(0, tableIndex - 600);
|
|
134986
135534
|
const windowEnd = Math.min(html.length, tableIndex + tableHtml.length + 400);
|
|
134987
135535
|
const nearby = html.slice(windowStart, windowEnd);
|
|
134988
|
-
return
|
|
135536
|
+
return /对比|竞品|竞争|功能|性能|对标|competitor|compare|benchmark/i.test(nearby);
|
|
134989
135537
|
}
|
|
134990
135538
|
function findFeatureCompareTableRows(html) {
|
|
134991
135539
|
const tables = html.match(/<table[\s\S]*?<\/table>/gi) ?? [];
|
|
@@ -135002,9 +135550,9 @@ function findFeatureCompareTableRows(html) {
|
|
|
135002
135550
|
return best;
|
|
135003
135551
|
}
|
|
135004
135552
|
function countPainPoints(html) {
|
|
135005
|
-
const labeled = (html.match(
|
|
135553
|
+
const labeled = (html.match(/(?:痛点|pain\s*point)\s*\d/gi) ?? []).length;
|
|
135006
135554
|
if (labeled >= 4) return labeled;
|
|
135007
|
-
const section = html.match(
|
|
135555
|
+
const section = html.match(/(?:痛点|pain points?)[\s\S]{0,3000}/i)?.[0] ?? html;
|
|
135008
135556
|
const listItems = (section.match(/<li[^>]*>/gi) ?? []).length;
|
|
135009
135557
|
return Math.max(labeled, listItems >= 4 ? 4 : listItems);
|
|
135010
135558
|
}
|
|
@@ -135020,7 +135568,7 @@ function hasEchartsInlineResize(html) {
|
|
|
135020
135568
|
return /addEventListener\s*\(\s*['"]resize['"]/.test(html) && /\.resize\s*\(/.test(html);
|
|
135021
135569
|
}
|
|
135022
135570
|
function countCompetitorMentions(html) {
|
|
135023
|
-
const competitorSection = html.match(/(?:主要)?竞品[\s\S]{0,5000}/i)?.[0] ?? html.match(/竞争对手[\s\S]{0,5000}/i)?.[0] ?? html.match(/对标(?:企业|品牌|公司)[\s\S]{0,5000}/i)?.[0] ?? "";
|
|
135571
|
+
const competitorSection = html.match(/(?:主要)?竞品[\s\S]{0,5000}/i)?.[0] ?? html.match(/竞争对手[\s\S]{0,5000}/i)?.[0] ?? html.match(/对标(?:企业|品牌|公司)[\s\S]{0,5000}/i)?.[0] ?? html.match(/competitors?[\s\S]{0,5000}/i)?.[0] ?? "";
|
|
135024
135572
|
if (competitorSection) {
|
|
135025
135573
|
const listItems = (competitorSection.match(/<li[^>]*>[\s\S]*?<\/li>/gi) ?? []).filter(
|
|
135026
135574
|
(li) => stripHtmlTags(li).trim().length >= 2
|
|
@@ -135061,8 +135609,10 @@ function splitMarketTokens(value) {
|
|
|
135061
135609
|
return value.split(/[、,,/|]/).map((t) => t.trim()).filter((t) => t.length >= 2);
|
|
135062
135610
|
}
|
|
135063
135611
|
function hasTargetGeoBreakdown(html, ctx) {
|
|
135064
|
-
const hasMetrics = /规模|增长|优先级|潜力|份额|CAGR
|
|
135065
|
-
|
|
135612
|
+
const hasMetrics = /规模|增长|优先级|潜力|份额|CAGR|市场容量|market size|growth|priority|share/i.test(
|
|
135613
|
+
html
|
|
135614
|
+
);
|
|
135615
|
+
const hasGeoFrame = /国家|区域|地区|市场|country|region|market/i.test(html);
|
|
135066
135616
|
if (!hasMetrics || !hasGeoFrame) return false;
|
|
135067
135617
|
const targetMarket = ctx.targetMarket?.trim() ?? "";
|
|
135068
135618
|
if (targetMarket) {
|
|
@@ -135079,56 +135629,58 @@ function hasTargetGeoBreakdown(html, ctx) {
|
|
|
135079
135629
|
return regionHits >= 2;
|
|
135080
135630
|
}
|
|
135081
135631
|
function hasReportTitle(html, ctx) {
|
|
135082
|
-
const hasTitle = /战略市场分析|KA
|
|
135632
|
+
const hasTitle = /战略市场分析|KA客户|行业分析报告|市场分析报告|行业调查|市场调查|industry analysis|market analysis|strategic market/i.test(
|
|
135633
|
+
html
|
|
135634
|
+
);
|
|
135083
135635
|
if (!hasTitle) return false;
|
|
135084
135636
|
return /目标市场|全球市场|行业|细分|market/i.test(html) || !!ctx.targetMarket?.trim() || !!ctx.industry?.trim() || !!ctx.customerName?.trim();
|
|
135085
135637
|
}
|
|
135086
135638
|
var CONTENT_RULES = [
|
|
135087
135639
|
{ id: "cover", test: (h, ctx) => hasReportTitle(h, ctx) },
|
|
135088
135640
|
{ id: "cover-kpi", test: (h) => /核心结论|metric|kpi|结论|摘要|executive summary/i.test(h) },
|
|
135089
|
-
{ id: "ch1", test: (h) =>
|
|
135641
|
+
{ id: "ch1", test: (h) => /市场与趋势诊断|market and trend/i.test(h) },
|
|
135090
135642
|
{
|
|
135091
135643
|
id: "ch1-tam",
|
|
135092
|
-
test: (h) => (/TAM|SAM|SOM/.test(h) ||
|
|
135644
|
+
test: (h) => (/TAM|SAM|SOM/.test(h) || /市场规模|market size/i.test(h)) && /CAGR|增长率|增长趋势|growth/i.test(h)
|
|
135093
135645
|
},
|
|
135094
|
-
{ id: "ch1-value-chain", test: (h) =>
|
|
135646
|
+
{ id: "ch1-value-chain", test: (h) => /价值链|生态定位|产业链|value chain|ecosystem/i.test(h) },
|
|
135095
135647
|
{ id: "ch1-target-geo", test: (h, ctx) => hasTargetGeoBreakdown(h, ctx) },
|
|
135096
|
-
{ id: "ch1-pestel", test: (h) => /PESTEL
|
|
135097
|
-
{ id: "ch1-forecast", test: (h) => /预测|3.?5年|未来\d
|
|
135098
|
-
{ id: "ch2", test: (h) =>
|
|
135648
|
+
{ id: "ch1-pestel", test: (h) => /PESTEL|政策|法规环境|技术趋势|经济|社会|环境|policy|regulatory/i.test(h) },
|
|
135649
|
+
{ id: "ch1-forecast", test: (h) => /预测|3.?5年|未来\d|forecast|next \d/i.test(h) },
|
|
135650
|
+
{ id: "ch2", test: (h) => /行业深度洞察|目标行业|industry insight|target industry/i.test(h) },
|
|
135099
135651
|
{ id: "ch2-pain", test: (h, ctx) => ctx.painPointCount >= 4 },
|
|
135100
|
-
{ id: "ch2-compliance", test: (h) =>
|
|
135652
|
+
{ id: "ch2-compliance", test: (h) => /法规|合规|regulation|compliance/i.test(h) && /<table/.test(h) },
|
|
135101
135653
|
{
|
|
135102
135654
|
id: "ch2-bpmn",
|
|
135103
|
-
test: (h) => /原流程|BPMN
|
|
135655
|
+
test: (h) => /原流程|BPMN|介入后|新流程|as-is|to-be|current process/i.test(h) && /效率|成本|提升|下降|节约|efficiency|cost|improve/i.test(h)
|
|
135104
135656
|
},
|
|
135105
|
-
{ id: "ch3", test: (h) =>
|
|
135106
|
-
{ id: "ch3-audience", test: (h) =>
|
|
135107
|
-
{ id: "ch3-scenario", test: (h) =>
|
|
135108
|
-
{ id: "ch4", test: (h) => /竞争策略|竞争.{0,6}
|
|
135657
|
+
{ id: "ch3", test: (h) => /目标受众|受众与场景|target audience|audience and scenario/i.test(h) },
|
|
135658
|
+
{ id: "ch3-audience", test: (h) => /用户|受众|画像|群体|audience|persona|segment/i.test(h) && /<table/.test(h) },
|
|
135659
|
+
{ id: "ch3-scenario", test: (h) => /应用场景|场景|差异化|用户价值|企业价值|use case|scenario/i.test(h) },
|
|
135660
|
+
{ id: "ch4", test: (h) => /竞争策略|竞争.{0,6}定位|competitive (strategy|positioning)/i.test(h) },
|
|
135109
135661
|
{ id: "ch4-competitors", test: (h, ctx) => ctx.competitorCount >= 3 },
|
|
135110
135662
|
{ id: "ch4-compare-table", test: (h, ctx) => ctx.competitorTableRows >= 11 },
|
|
135111
135663
|
{
|
|
135112
135664
|
id: "ch4-gaps",
|
|
135113
135665
|
test: (h) => [
|
|
135114
|
-
|
|
135115
|
-
|
|
135116
|
-
|
|
135117
|
-
|
|
135666
|
+
/功能空白|功能.*空白|feature gap/i.test(h),
|
|
135667
|
+
/场景|scenario/i.test(h),
|
|
135668
|
+
/用户群|用户|audience|segment/i.test(h),
|
|
135669
|
+
/地域|地区|区域|geo|region/i.test(h)
|
|
135118
135670
|
].filter(Boolean).length >= 3
|
|
135119
135671
|
},
|
|
135120
|
-
{ id: "ch4-positioning", test: (h) =>
|
|
135121
|
-
{ id: "ch5", test: (h) => /增长与品牌|GTM
|
|
135122
|
-
{ id: "ch5-gtm", test: (h) =>
|
|
135123
|
-
{ id: "ch5-brand", test: (h) =>
|
|
135124
|
-
{ id: "ch5-tactics", test: (h) => /内容营销|渠道|KOL
|
|
135125
|
-
{ id: "ch6", test: (h) =>
|
|
135126
|
-
{ id: "ch6-milestone", test: (h) =>
|
|
135127
|
-
{ id: "ch6-budget", test: (h) =>
|
|
135128
|
-
{ id: "ch6-risk", test: (h) =>
|
|
135129
|
-
{ id: "appendix", test: (h) =>
|
|
135130
|
-
{ id: "appendix-sources", test: (h) => /数据来源|Source:|报告名称|发布日期|http
|
|
135131
|
-
{ id: "appendix-methods", test: (h) =>
|
|
135672
|
+
{ id: "ch4-positioning", test: (h) => /定位陈述|定位:|核心定位|差异化|positioning|differentiat/i.test(h) },
|
|
135673
|
+
{ id: "ch5", test: (h) => /增长与品牌|GTM|growth and brand/i.test(h) },
|
|
135674
|
+
{ id: "ch5-gtm", test: (h) => /试点|规模复制|生态扩展|三阶段|pilot|scale|three phases/i.test(h) && /KPI|ROI|指标|metric/i.test(h) },
|
|
135675
|
+
{ id: "ch5-brand", test: (h) => /品牌|传播|主张|brand|message/i.test(h) },
|
|
135676
|
+
{ id: "ch5-tactics", test: (h) => /内容营销|渠道|KOL|销售模式|营销|content marketing|channel/i.test(h) },
|
|
135677
|
+
{ id: "ch6", test: (h) => /实施|implementation/i.test(h) && /风险|资源|risk|resource/i.test(h) },
|
|
135678
|
+
{ id: "ch6-milestone", test: (h) => /里程碑|阶段|milestone|phase/i.test(h) && /任务|负责人|成果|指标|owner|deliverable/i.test(h) },
|
|
135679
|
+
{ id: "ch6-budget", test: (h) => /预算|资源需求|人力|分配|budget|headcount/i.test(h) },
|
|
135680
|
+
{ id: "ch6-risk", test: (h) => /风险|risk/i.test(h) && /应对|措施|矩阵|mitigation|matrix/i.test(h) },
|
|
135681
|
+
{ id: "appendix", test: (h) => /附录|数据来源|appendix|sources/i.test(h) },
|
|
135682
|
+
{ id: "appendix-sources", test: (h) => /数据来源|Source:|报告名称|发布日期|http/i.test(h) },
|
|
135683
|
+
{ id: "appendix-methods", test: (h) => /调研方法|桌面研究|访谈|问卷|desk research|interview|survey/i.test(h) },
|
|
135132
135684
|
{
|
|
135133
135685
|
id: "appendix-glossary",
|
|
135134
135686
|
test: (h) => [/ROI/.test(h), /CAGR/.test(h), /GTM/.test(h), /BPMN/.test(h)].filter(Boolean).length >= 3
|
|
@@ -135193,6 +135745,7 @@ function formatMarketReportContentErrors(result) {
|
|
|
135193
135745
|
}
|
|
135194
135746
|
|
|
135195
135747
|
// src/commands/market-analysis/render-report.ts
|
|
135748
|
+
init_lang();
|
|
135196
135749
|
function asRecord6(value) {
|
|
135197
135750
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
135198
135751
|
return value;
|
|
@@ -135236,6 +135789,16 @@ async function runMarketAnalysisRender(opts) {
|
|
|
135236
135789
|
process.exit(1);
|
|
135237
135790
|
}
|
|
135238
135791
|
const reportData = asRecord6(dataRaw);
|
|
135792
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: reportData.meta });
|
|
135793
|
+
try {
|
|
135794
|
+
assertHtmlLangMatches(html, lang);
|
|
135795
|
+
} catch (err) {
|
|
135796
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
135797
|
+
console.error(`
|
|
135798
|
+
\u274C ${message}
|
|
135799
|
+
`);
|
|
135800
|
+
process.exit(1);
|
|
135801
|
+
}
|
|
135239
135802
|
const contentCheck = validateMarketReportContent(html, validationContextFromReport(reportData));
|
|
135240
135803
|
if (!contentCheck.ok) {
|
|
135241
135804
|
console.error(`
|
|
@@ -135287,10 +135850,11 @@ function registerMarketAnalysisCommands(program2) {
|
|
|
135287
135850
|
});
|
|
135288
135851
|
}
|
|
135289
135852
|
);
|
|
135290
|
-
root.command("render").description("\u6839\u636E Agent \u751F\u6210\u7684 market-report.json\uFF08\u542B htmlContent\uFF09\u5199\u51FA HTML \u7EC8\u7A3F").requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 market-report.json").option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
135853
|
+
root.command("render").description("\u6839\u636E Agent \u751F\u6210\u7684 market-report.json\uFF08\u542B htmlContent\uFF09\u5199\u51FA HTML \u7EC8\u7A3F").requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 market-report.json").option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u987B\u4E0E html lang \u4E00\u81F4").action(async (opts) => {
|
|
135291
135854
|
await runMarketAnalysisRender({
|
|
135292
135855
|
dataFile: opts.data,
|
|
135293
|
-
out: opts.out
|
|
135856
|
+
out: opts.out,
|
|
135857
|
+
lang: opts.lang
|
|
135294
135858
|
});
|
|
135295
135859
|
});
|
|
135296
135860
|
}
|
|
@@ -137467,6 +138031,8 @@ function applyDataRenderedCopy(data) {
|
|
|
137467
138031
|
}
|
|
137468
138032
|
|
|
137469
138033
|
// src/commands/google-ads-diagnosis/render-report.ts
|
|
138034
|
+
init_lang();
|
|
138035
|
+
init_html();
|
|
137470
138036
|
function asRecord16(value) {
|
|
137471
138037
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
137472
138038
|
return value;
|
|
@@ -137590,9 +138156,10 @@ async function runGoogleAdsDiagnosisRender(opts) {
|
|
|
137590
138156
|
`);
|
|
137591
138157
|
process.exit(1);
|
|
137592
138158
|
}
|
|
138159
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
137593
138160
|
let rendered;
|
|
137594
138161
|
try {
|
|
137595
|
-
rendered = injectGoogleAdsDiagnosisData(html, data);
|
|
138162
|
+
rendered = injectGoogleAdsDiagnosisData(localizeReportHtml(html, lang), stampMetaLang(data, lang));
|
|
137596
138163
|
} catch (err) {
|
|
137597
138164
|
const message = err instanceof Error ? err.message : String(err);
|
|
137598
138165
|
console.error(`
|
|
@@ -137656,14 +138223,15 @@ function registerGoogleAdsDiagnosisCommands(program2) {
|
|
|
137656
138223
|
"--no-merge-collect",
|
|
137657
138224
|
"\u4E0D\u4ECE collect \u81EA\u52A8\u6062\u590D campaigns/geographic/keywords.items",
|
|
137658
138225
|
false
|
|
137659
|
-
).option("--lenient", "\u7ED3\u6784\u8B66\u544A\uFF08\u5982\u7F3A analysis\uFF09\u65F6\u4E0D\u963B\u65AD\u6E32\u67D3", false).action(
|
|
138226
|
+
).option("--lenient", "\u7ED3\u6784\u8B66\u544A\uFF08\u5982\u7F3A analysis\uFF09\u65F6\u4E0D\u963B\u65AD\u6E32\u67D3", false).option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(
|
|
137660
138227
|
async (opts) => {
|
|
137661
138228
|
await runGoogleAdsDiagnosisRender({
|
|
137662
138229
|
dataFile: opts.data,
|
|
137663
138230
|
out: opts.out,
|
|
137664
138231
|
collectFile: opts.collect,
|
|
137665
138232
|
noMergeCollect: opts.noMergeCollect,
|
|
137666
|
-
lenient: opts.lenient
|
|
138233
|
+
lenient: opts.lenient,
|
|
138234
|
+
lang: opts.lang
|
|
137667
138235
|
});
|
|
137668
138236
|
}
|
|
137669
138237
|
);
|
|
@@ -138044,15 +138612,27 @@ function utcToIso(ms) {
|
|
|
138044
138612
|
const d = new Date(ms);
|
|
138045
138613
|
return isoDate(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
|
|
138046
138614
|
}
|
|
138047
|
-
function reportPeriodChrome(current, previous) {
|
|
138048
|
-
const kind = classifyReportPeriod(current, previous);
|
|
138615
|
+
function reportPeriodChrome(current, previous, lang = "zh") {
|
|
138616
|
+
const kind = classifyReportPeriod(current, previous, lang);
|
|
138049
138617
|
if (kind.unit === "\u5B63\u5EA6") {
|
|
138050
|
-
return {
|
|
138618
|
+
return {
|
|
138619
|
+
...kind,
|
|
138620
|
+
reportTitle: lang === "en" ? "Google quarterly business report" : "Google \u5B63\u5EA6\u7ECF\u8425\u62A5\u544A",
|
|
138621
|
+
coverEn: "QUARTERLY REPORT"
|
|
138622
|
+
};
|
|
138051
138623
|
}
|
|
138052
138624
|
if (kind.unit === "\u6708\u5EA6") {
|
|
138053
|
-
return {
|
|
138625
|
+
return {
|
|
138626
|
+
...kind,
|
|
138627
|
+
reportTitle: lang === "en" ? "Google monthly business report" : "Google \u6708\u5EA6\u7ECF\u8425\u62A5\u544A",
|
|
138628
|
+
coverEn: "MONTHLY REPORT"
|
|
138629
|
+
};
|
|
138054
138630
|
}
|
|
138055
|
-
return {
|
|
138631
|
+
return {
|
|
138632
|
+
...kind,
|
|
138633
|
+
reportTitle: lang === "en" ? "Google business report" : "Google \u7ECF\u8425\u62A5\u544A",
|
|
138634
|
+
coverEn: "PERFORMANCE REPORT"
|
|
138635
|
+
};
|
|
138056
138636
|
}
|
|
138057
138637
|
function lastCompleteQuarter(now = /* @__PURE__ */ new Date()) {
|
|
138058
138638
|
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
@@ -138892,6 +139472,8 @@ import { fileURLToPath as fileURLToPath8 } from "url";
|
|
|
138892
139472
|
var TSO_CLI_ROOT = path31.join(path31.dirname(fileURLToPath8(import.meta.url)), "../..");
|
|
138893
139473
|
|
|
138894
139474
|
// src/commands/google-quarterly/render-report.ts
|
|
139475
|
+
init_lang();
|
|
139476
|
+
init_html();
|
|
138895
139477
|
function asRecord18(value) {
|
|
138896
139478
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
138897
139479
|
return value;
|
|
@@ -138941,8 +139523,16 @@ async function runGoogleQuarterlyRender(opts) {
|
|
|
138941
139523
|
}
|
|
138942
139524
|
const outPath = path32.resolve(opts.out ?? path32.join(path32.dirname(dataPath), GOOGLE_QUARTERLY_HTML_BASENAME));
|
|
138943
139525
|
await fs27.mkdir(path32.dirname(outPath), { recursive: true });
|
|
138944
|
-
const
|
|
138945
|
-
const
|
|
139526
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: merged.meta });
|
|
139527
|
+
const periodChrome = reportPeriodChrome(
|
|
139528
|
+
readMetaRange(merged, "current"),
|
|
139529
|
+
readMetaRange(merged, "previous"),
|
|
139530
|
+
lang
|
|
139531
|
+
);
|
|
139532
|
+
const outHtml = injectQuarterlyReport(
|
|
139533
|
+
localizeReportHtml(html, lang),
|
|
139534
|
+
stampMetaLang({ ...merged, periodChrome }, lang)
|
|
139535
|
+
);
|
|
138946
139536
|
if (!outHtml.includes("homeCDN/echarts.min.js") || /new Chart\s*\(/.test(outHtml)) {
|
|
138947
139537
|
console.error("\n\u274C \u6A21\u677F\u5FC5\u987B\u4F7F\u7528 ECharts\uFF0C\u7981\u6B62 Chart.js\u3002\n");
|
|
138948
139538
|
process.exit(1);
|
|
@@ -138994,14 +139584,15 @@ function registerGoogleQuarterlyCommands(program2) {
|
|
|
138994
139584
|
});
|
|
138995
139585
|
}
|
|
138996
139586
|
);
|
|
138997
|
-
const render = root.command("render").description("\u5C06 Agent narrative + collect \u4E8B\u5B9E\u6CE8\u5165\u5B63\u5EA6 HTML").requiredOption("--data <file>", "Agent \u64B0\u5199\u7684 google-quarterly.json").option("--collect <file>", "collect JSON\uFF08\u9ED8\u8BA4\u540C\u76EE\u5F55 google-quarterly-collect.json\uFF09").option("--out <file>", "\u8F93\u51FA HTML").option("--lenient", "narrative \u7F3A\u9879\u65F6\u4ECD\u51FA HTML", false);
|
|
139587
|
+
const render = root.command("render").description("\u5C06 Agent narrative + collect \u4E8B\u5B9E\u6CE8\u5165\u5B63\u5EA6 HTML").requiredOption("--data <file>", "Agent \u64B0\u5199\u7684 google-quarterly.json").option("--collect <file>", "collect JSON\uFF08\u9ED8\u8BA4\u540C\u76EE\u5F55 google-quarterly-collect.json\uFF09").option("--out <file>", "\u8F93\u51FA HTML").option("--lenient", "narrative \u7F3A\u9879\u65F6\u4ECD\u51FA HTML", false).option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587");
|
|
138998
139588
|
render.action(
|
|
138999
139589
|
async (opts) => {
|
|
139000
139590
|
await runGoogleQuarterlyRender({
|
|
139001
139591
|
dataFile: opts.data,
|
|
139002
139592
|
collectFile: opts.collect,
|
|
139003
139593
|
out: opts.out,
|
|
139004
|
-
lenient: opts.lenient
|
|
139594
|
+
lenient: opts.lenient,
|
|
139595
|
+
lang: opts.lang
|
|
139005
139596
|
});
|
|
139006
139597
|
}
|
|
139007
139598
|
);
|
|
@@ -139412,6 +140003,9 @@ async function mergeFacebookSnapshotIntoReport(payload, snapshotDir) {
|
|
|
139412
140003
|
};
|
|
139413
140004
|
}
|
|
139414
140005
|
|
|
140006
|
+
// src/commands/facebook-analysis/render-excel.ts
|
|
140007
|
+
init_html();
|
|
140008
|
+
|
|
139415
140009
|
// src/commands/facebook-analysis/write-xlsx.ts
|
|
139416
140010
|
init_xlsx_style_engine();
|
|
139417
140011
|
var MIN_COL_WIDTH = 10;
|
|
@@ -139620,8 +140214,18 @@ function buildMetaPeriodExcelSheets(data) {
|
|
|
139620
140214
|
{ name: "\u53D7\u4F17", rows: audienceRows }
|
|
139621
140215
|
];
|
|
139622
140216
|
}
|
|
139623
|
-
function
|
|
139624
|
-
|
|
140217
|
+
function chrome2(text3, lang) {
|
|
140218
|
+
return lang === "en" ? applyEnglishPhrases(text3) : text3;
|
|
140219
|
+
}
|
|
140220
|
+
function writeMetaPeriodExcel(outPath, data, lang = "zh") {
|
|
140221
|
+
const sheets = buildMetaPeriodExcelSheets(data).map((sheet) => ({
|
|
140222
|
+
...sheet,
|
|
140223
|
+
name: chrome2(sheet.name, lang),
|
|
140224
|
+
rows: sheet.rows.map(
|
|
140225
|
+
(row, index) => index === 0 ? row.map((cell5) => typeof cell5 === "string" ? chrome2(cell5, lang) : cell5) : row
|
|
140226
|
+
)
|
|
140227
|
+
}));
|
|
140228
|
+
writeSimpleXlsx(outPath, sheets);
|
|
139625
140229
|
}
|
|
139626
140230
|
|
|
139627
140231
|
// src/commands/facebook-analysis/report-content.ts
|
|
@@ -139911,6 +140515,8 @@ function formatMetaPeriodReportErrors(result) {
|
|
|
139911
140515
|
|
|
139912
140516
|
// src/commands/facebook-analysis/render-report.ts
|
|
139913
140517
|
init_report_period();
|
|
140518
|
+
init_lang();
|
|
140519
|
+
init_html();
|
|
139914
140520
|
var TEMPLATE_BASENAMES2 = {
|
|
139915
140521
|
html: "meta-period-report.html"
|
|
139916
140522
|
};
|
|
@@ -139959,12 +140565,13 @@ function asRecord27(value) {
|
|
|
139959
140565
|
}
|
|
139960
140566
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
139961
140567
|
}
|
|
139962
|
-
function injectReportData3(html, payload) {
|
|
139963
|
-
const
|
|
139964
|
-
|
|
140568
|
+
function injectReportData3(html, payload, lang) {
|
|
140569
|
+
const localized = localizeReportHtml(html, lang);
|
|
140570
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
140571
|
+
if (!localized.includes(INJECT_MARKER2)) {
|
|
139965
140572
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 meta-period-report.html");
|
|
139966
140573
|
}
|
|
139967
|
-
return
|
|
140574
|
+
return localized.replace(INJECT_MARKER2, `window.__META_PERIOD_REPORT__ = ${json};`);
|
|
139968
140575
|
}
|
|
139969
140576
|
function defaultOutPath(dataPath, format, out) {
|
|
139970
140577
|
if (out?.trim()) {
|
|
@@ -139987,6 +140594,7 @@ async function runFacebookAnalysisRender(opts) {
|
|
|
139987
140594
|
data = await mergeFacebookSnapshotIntoReport(data, path42.resolve(opts.snapshotDir));
|
|
139988
140595
|
}
|
|
139989
140596
|
localizeFacebookReportLabels(data);
|
|
140597
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
139990
140598
|
const contentCheck = validateMetaPeriodReportContent(data);
|
|
139991
140599
|
if (!contentCheck.ok) {
|
|
139992
140600
|
console.error(`
|
|
@@ -140005,7 +140613,7 @@ async function runFacebookAnalysisRender(opts) {
|
|
|
140005
140613
|
const outPath = defaultOutPath(dataPath, format, opts.out);
|
|
140006
140614
|
await fsPromises3.mkdir(path42.dirname(outPath), { recursive: true });
|
|
140007
140615
|
if (format === "xlsx") {
|
|
140008
|
-
writeMetaPeriodExcel(outPath, data);
|
|
140616
|
+
writeMetaPeriodExcel(outPath, data, lang);
|
|
140009
140617
|
} else {
|
|
140010
140618
|
const templatePath = metaPeriodReportTemplatePath();
|
|
140011
140619
|
let html;
|
|
@@ -140018,7 +140626,7 @@ async function runFacebookAnalysisRender(opts) {
|
|
|
140018
140626
|
`);
|
|
140019
140627
|
process.exit(1);
|
|
140020
140628
|
}
|
|
140021
|
-
await fsPromises3.writeFile(outPath, injectReportData3(html, data), "utf8");
|
|
140629
|
+
await fsPromises3.writeFile(outPath, injectReportData3(html, data, lang), "utf8");
|
|
140022
140630
|
}
|
|
140023
140631
|
written.push(outPath);
|
|
140024
140632
|
}
|
|
@@ -140389,6 +140997,8 @@ function formatMetaDiagnosisReportErrors(result) {
|
|
|
140389
140997
|
}
|
|
140390
140998
|
|
|
140391
140999
|
// src/commands/facebook-analysis/diagnosis-render-report.ts
|
|
141000
|
+
init_lang();
|
|
141001
|
+
init_html();
|
|
140392
141002
|
var TEMPLATE_BASENAME2 = "meta-account-diagnosis-report.html";
|
|
140393
141003
|
var INJECT_MARKER3 = "window.__META_DIAGNOSIS_REPORT__ = window.__META_DIAGNOSIS_REPORT__ || null;";
|
|
140394
141004
|
function resolveSkillTemplatePath5(basename13) {
|
|
@@ -140420,12 +141030,13 @@ function asRecord30(value) {
|
|
|
140420
141030
|
}
|
|
140421
141031
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
140422
141032
|
}
|
|
140423
|
-
function injectReportData4(html, payload) {
|
|
140424
|
-
const
|
|
140425
|
-
|
|
141033
|
+
function injectReportData4(html, payload, lang) {
|
|
141034
|
+
const localized = localizeReportHtml(html, lang);
|
|
141035
|
+
const json = JSON.stringify(stampMetaLang(payload, lang)).replace(/</g, "\\u003c");
|
|
141036
|
+
if (!localized.includes(INJECT_MARKER3)) {
|
|
140426
141037
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 meta-account-diagnosis-report.html");
|
|
140427
141038
|
}
|
|
140428
|
-
return
|
|
141039
|
+
return localized.replace(INJECT_MARKER3, `window.__META_DIAGNOSIS_REPORT__ = ${json};`);
|
|
140429
141040
|
}
|
|
140430
141041
|
async function runFacebookAnalysisDiagnosisRender(opts) {
|
|
140431
141042
|
const dataPath = path44.resolve(opts.dataFile);
|
|
@@ -140433,6 +141044,7 @@ async function runFacebookAnalysisDiagnosisRender(opts) {
|
|
|
140433
141044
|
if (opts.snapshotDir?.trim()) {
|
|
140434
141045
|
data = await mergeMetaDiagnosisSnapshotIntoReport(data, path44.resolve(opts.snapshotDir));
|
|
140435
141046
|
}
|
|
141047
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
140436
141048
|
const contentCheck = validateMetaDiagnosisReportContent(data);
|
|
140437
141049
|
if (!contentCheck.ok) {
|
|
140438
141050
|
console.error(`
|
|
@@ -140462,7 +141074,7 @@ async function runFacebookAnalysisDiagnosisRender(opts) {
|
|
|
140462
141074
|
);
|
|
140463
141075
|
const outDir = path44.dirname(outPath);
|
|
140464
141076
|
await fsPromises4.mkdir(outDir, { recursive: true });
|
|
140465
|
-
await fsPromises4.writeFile(outPath, injectReportData4(html, data), "utf8");
|
|
141077
|
+
await fsPromises4.writeFile(outPath, injectReportData4(html, data, lang), "utf8");
|
|
140466
141078
|
const { stats } = contentCheck;
|
|
140467
141079
|
console.log(`
|
|
140468
141080
|
\u2705 Meta\uFF08Facebook\uFF09\u8D26\u6237\u8BCA\u65AD HTML \u62A5\u544A\u5DF2\u751F\u6210\uFF1A${outPath}
|
|
@@ -141152,12 +141764,13 @@ function registerFacebookAnalysisCommands(program2) {
|
|
|
141152
141764
|
"--format <html|xlsx>",
|
|
141153
141765
|
"\u9ED8\u8BA4 html\uFF08\u8FD0\u8425\u6D45\u8272\u6A21\u677F\uFF09\uFF1B\u7528\u6237\u8981\u8868\u683C / Excel \u65F6\u4F20 xlsx\uFF1B\u53EF\u9017\u53F7\u540C\u65F6\u8F93\u51FA html,xlsx",
|
|
141154
141766
|
"html"
|
|
141155
|
-
).action(async (opts) => {
|
|
141767
|
+
).option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
141156
141768
|
await runFacebookAnalysisRender({
|
|
141157
141769
|
dataFile: opts.data,
|
|
141158
141770
|
snapshotDir: opts.snapshotDir,
|
|
141159
141771
|
out: opts.out,
|
|
141160
|
-
format: opts.format
|
|
141772
|
+
format: opts.format,
|
|
141773
|
+
lang: opts.lang
|
|
141161
141774
|
});
|
|
141162
141775
|
});
|
|
141163
141776
|
root.command("diagnosis-render").description(
|
|
@@ -141165,11 +141778,12 @@ function registerFacebookAnalysisCommands(program2) {
|
|
|
141165
141778
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 meta-account-diagnosis-report.json").option(
|
|
141166
141779
|
"--snapshot-dir <dir>",
|
|
141167
141780
|
"\u53EF\u9009\uFF1Afacebook-analysis --json-out \u76EE\u5F55\uFF0C\u81EA\u52A8\u8865\u5168 meta / kpis\uFF08overview \u5FEB\u7167\uFF09"
|
|
141168
|
-
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
141781
|
+
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
141169
141782
|
await runFacebookAnalysisDiagnosisRender({
|
|
141170
141783
|
dataFile: opts.data,
|
|
141171
141784
|
snapshotDir: opts.snapshotDir,
|
|
141172
|
-
out: opts.out
|
|
141785
|
+
out: opts.out,
|
|
141786
|
+
lang: opts.lang
|
|
141173
141787
|
});
|
|
141174
141788
|
});
|
|
141175
141789
|
root.command("account-status").description(
|
|
@@ -142521,6 +143135,8 @@ function formatBingPeriodReportErrors(result) {
|
|
|
142521
143135
|
|
|
142522
143136
|
// src/commands/bing-analysis/render-report.ts
|
|
142523
143137
|
init_report_period();
|
|
143138
|
+
init_lang();
|
|
143139
|
+
init_html();
|
|
142524
143140
|
var TEMPLATE_BASENAME3 = "bing-period-report.html";
|
|
142525
143141
|
var INJECT_MARKER4 = "window.__BING_PERIOD_REPORT__ = window.__BING_PERIOD_REPORT__ || null;";
|
|
142526
143142
|
function resolveSkillTemplatePath6(basename13) {
|
|
@@ -142552,12 +143168,13 @@ function asRecord34(value) {
|
|
|
142552
143168
|
}
|
|
142553
143169
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
142554
143170
|
}
|
|
142555
|
-
function injectReportData5(html, payload) {
|
|
142556
|
-
const
|
|
142557
|
-
|
|
143171
|
+
function injectReportData5(html, payload, lang) {
|
|
143172
|
+
const localized = localizeReportHtml(html, lang);
|
|
143173
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
143174
|
+
if (!localized.includes(INJECT_MARKER4)) {
|
|
142558
143175
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 bing-period-report.html");
|
|
142559
143176
|
}
|
|
142560
|
-
return
|
|
143177
|
+
return localized.replace(INJECT_MARKER4, `window.__BING_PERIOD_REPORT__ = ${json};`);
|
|
142561
143178
|
}
|
|
142562
143179
|
async function runBingAnalysisRender(opts) {
|
|
142563
143180
|
const dataPath = path48.resolve(opts.dataFile);
|
|
@@ -142565,6 +143182,7 @@ async function runBingAnalysisRender(opts) {
|
|
|
142565
143182
|
if (opts.snapshotDir?.trim()) {
|
|
142566
143183
|
data = await mergeBingAnalysisSnapshotIntoReport(data, path48.resolve(opts.snapshotDir));
|
|
142567
143184
|
}
|
|
143185
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
142568
143186
|
const contentCheck = validateBingPeriodReportContent(data);
|
|
142569
143187
|
if (!contentCheck.ok) {
|
|
142570
143188
|
console.error(`
|
|
@@ -142594,7 +143212,7 @@ async function runBingAnalysisRender(opts) {
|
|
|
142594
143212
|
);
|
|
142595
143213
|
const outDir = path48.dirname(outPath);
|
|
142596
143214
|
await fsPromises5.mkdir(outDir, { recursive: true });
|
|
142597
|
-
await fsPromises5.writeFile(outPath, injectReportData5(html, data), "utf8");
|
|
143215
|
+
await fsPromises5.writeFile(outPath, injectReportData5(html, data, lang), "utf8");
|
|
142598
143216
|
const { stats } = contentCheck;
|
|
142599
143217
|
const cover = periodWord(attachPeriodChrome(data).periodChrome.unit, "\u8D26\u6237");
|
|
142600
143218
|
console.log(`
|
|
@@ -142661,11 +143279,12 @@ function registerBingAnalysisCommands(program2) {
|
|
|
142661
143279
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 bing-period-report.json").option(
|
|
142662
143280
|
"--snapshot-dir <dir>",
|
|
142663
143281
|
"\u53EF\u9009\uFF1Abing-analysis --json-out \u76EE\u5F55\uFF0C\u81EA\u52A8\u8865\u5168 meta / kpis\uFF08overview \u5FEB\u7167\uFF09"
|
|
142664
|
-
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
143282
|
+
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
142665
143283
|
await runBingAnalysisRender({
|
|
142666
143284
|
dataFile: opts.data,
|
|
142667
143285
|
snapshotDir: opts.snapshotDir,
|
|
142668
|
-
out: opts.out
|
|
143286
|
+
out: opts.out,
|
|
143287
|
+
lang: opts.lang
|
|
142669
143288
|
});
|
|
142670
143289
|
});
|
|
142671
143290
|
root.command("account-status").description("\u8D26\u6237\u72B6\u6001\uFF08GET \u2026/account-status\uFF1Bstatus=Active \u4E3A\u6B63\u5E38\u6295\u653E\uFF1B\u4E0D\u5E26\u65E5\u671F\u533A\u95F4\uFF09").requiredOption(...ACCOUNT_OPTION2).option("-t, --token <token>", "Auth Token").option("--json-out <path>", JSON_OUT_OPTION_DESC2, void 0).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
@@ -143420,6 +144039,8 @@ function formatTikTokPeriodReportErrors(result) {
|
|
|
143420
144039
|
|
|
143421
144040
|
// src/commands/tiktok-analysis/render-report.ts
|
|
143422
144041
|
init_report_period();
|
|
144042
|
+
init_lang();
|
|
144043
|
+
init_html();
|
|
143423
144044
|
var TEMPLATE_BASENAME4 = "tiktok-period-report.html";
|
|
143424
144045
|
var INJECT_MARKER5 = "window.__TIKTOK_PERIOD_REPORT__ = window.__TIKTOK_PERIOD_REPORT__ || null;";
|
|
143425
144046
|
function resolveSkillTemplatePath7(basename13) {
|
|
@@ -143451,12 +144072,13 @@ function asRecord37(value) {
|
|
|
143451
144072
|
}
|
|
143452
144073
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
143453
144074
|
}
|
|
143454
|
-
function injectReportData6(html, payload) {
|
|
143455
|
-
const
|
|
143456
|
-
|
|
144075
|
+
function injectReportData6(html, payload, lang) {
|
|
144076
|
+
const localized = localizeReportHtml(html, lang);
|
|
144077
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
144078
|
+
if (!localized.includes(INJECT_MARKER5)) {
|
|
143457
144079
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 tiktok-period-report.html");
|
|
143458
144080
|
}
|
|
143459
|
-
return
|
|
144081
|
+
return localized.replace(INJECT_MARKER5, `window.__TIKTOK_PERIOD_REPORT__ = ${json};`);
|
|
143460
144082
|
}
|
|
143461
144083
|
async function runTikTokAnalysisRender(opts) {
|
|
143462
144084
|
const dataPath = path51.resolve(opts.dataFile);
|
|
@@ -143464,6 +144086,7 @@ async function runTikTokAnalysisRender(opts) {
|
|
|
143464
144086
|
if (opts.snapshotDir?.trim()) {
|
|
143465
144087
|
data = await mergeTikTokAnalysisSnapshotIntoReport(data, path51.resolve(opts.snapshotDir));
|
|
143466
144088
|
}
|
|
144089
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
143467
144090
|
const contentCheck = validateTikTokPeriodReportContent(data);
|
|
143468
144091
|
if (!contentCheck.ok) {
|
|
143469
144092
|
console.error(`
|
|
@@ -143493,7 +144116,7 @@ async function runTikTokAnalysisRender(opts) {
|
|
|
143493
144116
|
);
|
|
143494
144117
|
const outDir = path51.dirname(outPath);
|
|
143495
144118
|
await fsPromises6.mkdir(outDir, { recursive: true });
|
|
143496
|
-
await fsPromises6.writeFile(outPath, injectReportData6(html, data), "utf8");
|
|
144119
|
+
await fsPromises6.writeFile(outPath, injectReportData6(html, data, lang), "utf8");
|
|
143497
144120
|
const { stats } = contentCheck;
|
|
143498
144121
|
const cover = periodWord(attachPeriodChrome(data).periodChrome.unit, "\u8D26\u6237");
|
|
143499
144122
|
console.log(`
|
|
@@ -144239,11 +144862,12 @@ function registerTikTokAnalysisCommands(program2) {
|
|
|
144239
144862
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 tiktok-period-report.json").option(
|
|
144240
144863
|
"--snapshot-dir <dir>",
|
|
144241
144864
|
"\u53EF\u9009\uFF1Atiktok-analysis --json-out \u76EE\u5F55\uFF0C\u81EA\u52A8\u8865\u5168 meta\uFF08accountId / \u65E5\u671F\u533A\u95F4 / \u8D27\u5E01\uFF09"
|
|
144242
|
-
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
144865
|
+
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
144243
144866
|
await runTikTokAnalysisRender({
|
|
144244
144867
|
dataFile: opts.data,
|
|
144245
144868
|
snapshotDir: opts.snapshotDir,
|
|
144246
|
-
out: opts.out
|
|
144869
|
+
out: opts.out,
|
|
144870
|
+
lang: opts.lang
|
|
144247
144871
|
});
|
|
144248
144872
|
});
|
|
144249
144873
|
root.command("areacode").description("TikTok \u5730\u533A\u4EE3\u7801\u679A\u4E3E\uFF08\u4E3B\u5E73\u53F0 query/media-account/tiktok/TikTokAreacode/Read\uFF09").option("-t, --token <token>", "Auth Token").option(
|
|
@@ -145196,6 +145820,8 @@ function formatYandexPeriodReportErrors(result) {
|
|
|
145196
145820
|
|
|
145197
145821
|
// src/commands/yandex-analysis/render-report.ts
|
|
145198
145822
|
init_report_period();
|
|
145823
|
+
init_lang();
|
|
145824
|
+
init_html();
|
|
145199
145825
|
var TEMPLATE_BASENAME5 = "yandex-period-report.html";
|
|
145200
145826
|
var INJECT_MARKER6 = "window.__YANDEX_PERIOD_REPORT__ = window.__YANDEX_PERIOD_REPORT__ || null;";
|
|
145201
145827
|
function resolveSkillTemplatePath8(basename13) {
|
|
@@ -145240,12 +145866,13 @@ function refreshWeeklyFromDaily(data) {
|
|
|
145240
145866
|
}
|
|
145241
145867
|
};
|
|
145242
145868
|
}
|
|
145243
|
-
function injectReportData7(html, payload) {
|
|
145244
|
-
const
|
|
145245
|
-
|
|
145869
|
+
function injectReportData7(html, payload, lang) {
|
|
145870
|
+
const localized = localizeReportHtml(html, lang);
|
|
145871
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
145872
|
+
if (!localized.includes(INJECT_MARKER6)) {
|
|
145246
145873
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 yandex-period-report.html");
|
|
145247
145874
|
}
|
|
145248
|
-
return
|
|
145875
|
+
return localized.replace(INJECT_MARKER6, `window.__YANDEX_PERIOD_REPORT__ = ${json};`);
|
|
145249
145876
|
}
|
|
145250
145877
|
async function runYandexAnalysisRender(opts) {
|
|
145251
145878
|
const dataPath = path54.resolve(opts.dataFile);
|
|
@@ -145254,6 +145881,7 @@ async function runYandexAnalysisRender(opts) {
|
|
|
145254
145881
|
data = await mergeYandexAnalysisSnapshotIntoReport(data, path54.resolve(opts.snapshotDir));
|
|
145255
145882
|
}
|
|
145256
145883
|
data = refreshWeeklyFromDaily(data);
|
|
145884
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
145257
145885
|
const contentCheck = validateYandexPeriodReportContent(data);
|
|
145258
145886
|
if (!contentCheck.ok) {
|
|
145259
145887
|
console.error(`
|
|
@@ -145281,7 +145909,7 @@ async function runYandexAnalysisRender(opts) {
|
|
|
145281
145909
|
);
|
|
145282
145910
|
const outDir = path54.dirname(outPath);
|
|
145283
145911
|
await fsPromises7.mkdir(outDir, { recursive: true });
|
|
145284
|
-
await fsPromises7.writeFile(outPath, injectReportData7(html, data), "utf8");
|
|
145912
|
+
await fsPromises7.writeFile(outPath, injectReportData7(html, data, lang), "utf8");
|
|
145285
145913
|
const { stats } = contentCheck;
|
|
145286
145914
|
const cover = periodWord(attachPeriodChrome(data).periodChrome.unit, "\u8D26\u6237");
|
|
145287
145915
|
console.log(`
|
|
@@ -145793,11 +146421,12 @@ function registerYandexAnalysisCommands(program2) {
|
|
|
145793
146421
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 yandex-period-report.json").option(
|
|
145794
146422
|
"--snapshot-dir <dir>",
|
|
145795
146423
|
"\u53EF\u9009\uFF1Ayandex-analysis --json-out \u76EE\u5F55\uFF0C\u81EA\u52A8\u8865\u5168 meta / kpis / tables"
|
|
145796
|
-
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
|
|
146424
|
+
).option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").option("--lang <lang>", "\u7EC8\u7A3F\u8BED\u8A00\uFF1Azh \u6216 en\u3002\u8986\u76D6 JSON meta.lang\uFF1B\u90FD\u6CA1\u6709\u5219\u4E2D\u6587").action(async (opts) => {
|
|
145797
146425
|
await runYandexAnalysisRender({
|
|
145798
146426
|
dataFile: opts.data,
|
|
145799
146427
|
snapshotDir: opts.snapshotDir,
|
|
145800
|
-
out: opts.out
|
|
146428
|
+
out: opts.out,
|
|
146429
|
+
lang: opts.lang
|
|
145801
146430
|
});
|
|
145802
146431
|
});
|
|
145803
146432
|
root.command("account-status").description(
|