siluzan-tso-cli 1.1.60-beta.2 → 1.1.60
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 -2
- package/dist/index.js +999 -256
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/assets/pmax-patch-campaign-template.json +1 -1
- package/dist/skill/references/accounts/accounts-list.md +1 -1
- package/dist/skill/references/accounts/accounts-permissions.md +2 -2
- package/dist/skill/references/accounts/finance.md +1 -1
- package/dist/skill/references/accounts/open-account-by-media.md +1 -1
- package/dist/skill/references/accounts/open-account-google-ui.md +1 -1
- package/dist/skill/references/analytics/rag.md +1 -1
- package/dist/skill/references/analytics/reporting.md +5 -5
- package/dist/skill/references/core/agent-conventions.md +10 -0
- package/dist/skill/references/core/playbooks.md +12 -11
- package/dist/skill/references/core/setup.md +5 -5
- package/dist/skill/references/core/workflows.md +1 -1
- package/dist/skill/references/google-ads/google-ads-write.md +3 -3
- package/dist/skill/references/google-ads/pmax-api.md +4 -4
- package/dist/skill/references/misc/tso-home.md +2 -2
- 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 +3 -3
- package/dist/skill/scripts/install.sh +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4051,7 +4051,7 @@ var DEFAULT_API_BASE;
|
|
|
4051
4051
|
var init_defaults = __esm({
|
|
4052
4052
|
"src/config/defaults.ts"() {
|
|
4053
4053
|
"use strict";
|
|
4054
|
-
DEFAULT_API_BASE = "https://tso-api
|
|
4054
|
+
DEFAULT_API_BASE = "https://tso-api.siluzan.com";
|
|
4055
4055
|
}
|
|
4056
4056
|
});
|
|
4057
4057
|
|
|
@@ -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
|
|
@@ -122189,6 +122720,16 @@ function pmaxAssetGroupReportUrl(googleApiUrl, accountId, query) {
|
|
|
122189
122720
|
const qs = query.toString();
|
|
122190
122721
|
return `${base}/reporting/media-account/${accountId}/pmax/asset-groups/reports${qs ? `?${qs}` : ""}`;
|
|
122191
122722
|
}
|
|
122723
|
+
function pmaxAssetReportUrl(googleApiUrl, accountId, query) {
|
|
122724
|
+
const base = googleApiUrl.replace(/\/$/, "");
|
|
122725
|
+
const qs = query.toString();
|
|
122726
|
+
return `${base}/reporting/media-account/${accountId}/pmax/asset-groups/reports/assets${qs ? `?${qs}` : ""}`;
|
|
122727
|
+
}
|
|
122728
|
+
function pmaxChannelReportUrl(googleApiUrl, accountId, query) {
|
|
122729
|
+
const base = googleApiUrl.replace(/\/$/, "");
|
|
122730
|
+
const qs = query.toString();
|
|
122731
|
+
return `${base}/reporting/media-account/${accountId}/pmax/campaigns/reports/channels${qs ? `?${qs}` : ""}`;
|
|
122732
|
+
}
|
|
122192
122733
|
function pmaxGeoReportUrl(googleApiUrl, accountId, query) {
|
|
122193
122734
|
const base = googleApiUrl.replace(/\/$/, "");
|
|
122194
122735
|
const qs = query.toString();
|
|
@@ -124845,6 +125386,80 @@ PMax \u8D44\u4EA7\u7EC4\u6548\u679C\u62A5\u8868\uFF08${query.get("startDate")} ~
|
|
|
124845
125386
|
console.log(" \u5B8C\u6574\u6570\u636E\u8BF7\u4F7F\u7528 --json-out\n");
|
|
124846
125387
|
});
|
|
124847
125388
|
}
|
|
125389
|
+
async function runAdPmaxReportAssets(opts) {
|
|
125390
|
+
const accountId = requireAccountId(opts.account);
|
|
125391
|
+
const query = buildReportQuery(opts);
|
|
125392
|
+
await withGoogleApi(opts, async (config, googleApiUrl) => {
|
|
125393
|
+
const url = pmaxAssetReportUrl(googleApiUrl, accountId, query);
|
|
125394
|
+
let data;
|
|
125395
|
+
try {
|
|
125396
|
+
const raw = await pmaxApiFetch(url, config, {}, opts.verbose);
|
|
125397
|
+
data = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : { data: raw };
|
|
125398
|
+
} catch (err) {
|
|
125399
|
+
console.error(
|
|
125400
|
+
`
|
|
125401
|
+
\u274C \u83B7\u53D6 PMax \u7D20\u6750\u62A5\u8868\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
125402
|
+
`
|
|
125403
|
+
);
|
|
125404
|
+
process.exit(1);
|
|
125405
|
+
}
|
|
125406
|
+
if (await emitPmaxResult(
|
|
125407
|
+
{ ...opts, account: accountId },
|
|
125408
|
+
`ad-pmax-report-assets-${accountId}`,
|
|
125409
|
+
"ad pmax-report-assets",
|
|
125410
|
+
data,
|
|
125411
|
+
accountId
|
|
125412
|
+
)) {
|
|
125413
|
+
return;
|
|
125414
|
+
}
|
|
125415
|
+
const assets = data["assets"];
|
|
125416
|
+
const n = Array.isArray(assets) ? assets.length : 0;
|
|
125417
|
+
console.log(
|
|
125418
|
+
`
|
|
125419
|
+
PMax \u7D20\u6750\u62A5\u8868\uFF08${query.get("startDate")} ~ ${query.get("endDate")}\uFF0C${n} \u6761\u7D20\u6750\uFF09
|
|
125420
|
+
`
|
|
125421
|
+
);
|
|
125422
|
+
console.log(" \u6BD4\u7387\u6309\u672C\u8868\u5408\u8BA1\u3002\u4E0E\u7D20\u6750\u7EC4\u82B1\u8D39/\u70B9\u51FB\u4E0D\u5FC5\u76F8\u7B49\u3002\u7D20\u6750\u70B9\u51FB\u53EF\u5927\u4E8E\u7CFB\u5217\u70B9\u51FB\u3002");
|
|
125423
|
+
console.log(" \u5B8C\u6574\u6570\u636E\u8BF7\u4F7F\u7528 --json-out\n");
|
|
125424
|
+
});
|
|
125425
|
+
}
|
|
125426
|
+
async function runAdPmaxReportChannels(opts) {
|
|
125427
|
+
const accountId = requireAccountId(opts.account);
|
|
125428
|
+
const query = buildReportQuery(opts);
|
|
125429
|
+
await withGoogleApi(opts, async (config, googleApiUrl) => {
|
|
125430
|
+
const url = pmaxChannelReportUrl(googleApiUrl, accountId, query);
|
|
125431
|
+
let data;
|
|
125432
|
+
try {
|
|
125433
|
+
const raw = await pmaxApiFetch(url, config, {}, opts.verbose);
|
|
125434
|
+
data = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : { data: raw };
|
|
125435
|
+
} catch (err) {
|
|
125436
|
+
console.error(
|
|
125437
|
+
`
|
|
125438
|
+
\u274C \u83B7\u53D6 PMax \u6E20\u9053\u62A5\u8868\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
125439
|
+
`
|
|
125440
|
+
);
|
|
125441
|
+
process.exit(1);
|
|
125442
|
+
}
|
|
125443
|
+
if (await emitPmaxResult(
|
|
125444
|
+
{ ...opts, account: accountId },
|
|
125445
|
+
`ad-pmax-report-channels-${accountId}`,
|
|
125446
|
+
"ad pmax-report-channels",
|
|
125447
|
+
data,
|
|
125448
|
+
accountId
|
|
125449
|
+
)) {
|
|
125450
|
+
return;
|
|
125451
|
+
}
|
|
125452
|
+
const campaigns = data["campaigns"];
|
|
125453
|
+
const n = Array.isArray(campaigns) ? campaigns.length : 0;
|
|
125454
|
+
console.log(
|
|
125455
|
+
`
|
|
125456
|
+
PMax \u6E20\u9053\u62A5\u8868\uFF08${query.get("startDate")} ~ ${query.get("endDate")}\uFF0C${n} \u4E2A\u7CFB\u5217\uFF09
|
|
125457
|
+
`
|
|
125458
|
+
);
|
|
125459
|
+
console.log(" \u5408\u8BA1\u53EA\u542B\u5404\u7F51\u7EDC\u4E4B\u548C\u3002\u89C6\u9891\u3001\u5546\u54C1\u662F\u5BF9\u7167\uFF0C\u4E0D\u52A0\u5165\u5408\u8BA1\u3002");
|
|
125460
|
+
console.log(" \u5B8C\u6574\u6570\u636E\u8BF7\u4F7F\u7528 --json-out\n");
|
|
125461
|
+
});
|
|
125462
|
+
}
|
|
124848
125463
|
async function runAdPmaxReportGeo(opts) {
|
|
124849
125464
|
const accountId = requireAccountId(opts.account);
|
|
124850
125465
|
const query = buildReportQuery(opts);
|
|
@@ -124880,6 +125495,9 @@ PMax \u5730\u7406\u62A5\u8868\uFF08\u6D3B\u52A8\xD7\u56FD\u5BB6\uFF0C${query.get
|
|
|
124880
125495
|
});
|
|
124881
125496
|
}
|
|
124882
125497
|
|
|
125498
|
+
// src/commands/ad/_register.ts
|
|
125499
|
+
init_lang();
|
|
125500
|
+
|
|
124883
125501
|
// src/commands/ad/campaign-validate.ts
|
|
124884
125502
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
124885
125503
|
init_cli_json_snapshot();
|
|
@@ -125248,7 +125866,7 @@ function register21(program2) {
|
|
|
125248
125866
|
).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
125867
|
"--md-out <path>",
|
|
125250
125868
|
"\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(
|
|
125869
|
+
).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
125870
|
async (opts) => {
|
|
125253
125871
|
await runCampaignBatchDiff({
|
|
125254
125872
|
token: opts.token,
|
|
@@ -125258,7 +125876,8 @@ function register21(program2) {
|
|
|
125258
125876
|
account: opts.account,
|
|
125259
125877
|
jsonOut: opts.jsonOut,
|
|
125260
125878
|
mdOut: opts.mdOut,
|
|
125261
|
-
verbose: opts.verbose
|
|
125879
|
+
verbose: opts.verbose,
|
|
125880
|
+
lang: readReportLangOrExit({ flag: opts.lang })
|
|
125262
125881
|
});
|
|
125263
125882
|
}
|
|
125264
125883
|
);
|
|
@@ -125704,7 +126323,7 @@ function register21(program2) {
|
|
|
125704
126323
|
);
|
|
125705
126324
|
addPmaxJsonOptions(
|
|
125706
126325
|
adCmd.command("pmax-edit").description(
|
|
125707
|
-
"\u66F4\u65B0 PMax \u6D3B\u52A8\uFF08PATCH\uFF1B\u52FF\u7528 ad campaign-edit\uFF09\n --patch-file \u89C1 assets/pmax-patch-campaign-template.json"
|
|
126326
|
+
"\u66F4\u65B0 PMax \u6D3B\u52A8\uFF08PATCH\uFF1B\u52FF\u7528 ad campaign-edit\uFF09\n --patch-file \u89C1 assets/pmax-patch-campaign-template.json\uFF1BassetAutomationSettings \u53EA\u6539\u63D0\u4EA4\u7684\u7C7B\u578B"
|
|
125708
126327
|
).requiredOption("-a, --account <id>", "Google \u5A92\u4F53\u5BA2\u6237 ID").requiredOption("--campaign-id <id>", "\u6D3B\u52A8 ID").option("--patch-file <path>", "PATCH JSON\uFF08budget/targetCpa \u586B\u5143\uFF09").option(
|
|
125709
126328
|
"--status <status>",
|
|
125710
126329
|
"2|3|4 \u6216 Enabled|Paused|Removed\uFF08Removed \u4E0D\u53EF\u6062\u590D\uFF0C\u987B\u7528\u6237\u540C\u610F\u540E\u52A0 --i-confirm\uFF09"
|
|
@@ -125790,7 +126409,7 @@ function register21(program2) {
|
|
|
125790
126409
|
}
|
|
125791
126410
|
);
|
|
125792
126411
|
addPmaxJsonOptions(
|
|
125793
|
-
adCmd.command("pmax-signals-set").description("\u5168\u91CF\u540C\u6B65\u8D44\u4EA7\u7EC4\u4FE1\u53F7\uFF08PUT .../signals\uFF1B\
|
|
126412
|
+
adCmd.command("pmax-signals-set").description("\u5168\u91CF\u540C\u6B65\u8D44\u4EA7\u7EC4\u4FE1\u53F7\uFF08PUT .../signals\uFF1B\u4E24\u7C7B\u90FD\u7A7A\u4E14\u7EC4\u91CC\u8FD8\u6709\u4FE1\u53F7\u4F1A 400\uFF09").requiredOption("--config-file <path>", "JSON \u914D\u7F6E\u8DEF\u5F84").option("-t, --token <token>", "Auth Token")
|
|
125794
126413
|
).action(
|
|
125795
126414
|
async (opts) => {
|
|
125796
126415
|
await runAdPmaxSignalsSet(opts);
|
|
@@ -125854,6 +126473,36 @@ function register21(program2) {
|
|
|
125854
126473
|
});
|
|
125855
126474
|
}
|
|
125856
126475
|
);
|
|
126476
|
+
pmaxReportOpts(
|
|
126477
|
+
adCmd.command("pmax-report-assets").description("PMax \u5355\u7D20\u6750\u62A5\u8868\uFF08GET .../pmax/asset-groups/reports/assets\uFF09")
|
|
126478
|
+
).action(
|
|
126479
|
+
async (opts) => {
|
|
126480
|
+
await runAdPmaxReportAssets({
|
|
126481
|
+
account: opts.account,
|
|
126482
|
+
startDate: opts.start,
|
|
126483
|
+
endDate: opts.end,
|
|
126484
|
+
campaignId: opts.campaignId,
|
|
126485
|
+
token: opts.token,
|
|
126486
|
+
jsonOut: opts.jsonOut,
|
|
126487
|
+
verbose: opts.verbose
|
|
126488
|
+
});
|
|
126489
|
+
}
|
|
126490
|
+
);
|
|
126491
|
+
pmaxReportOpts(
|
|
126492
|
+
adCmd.command("pmax-report-channels").description("PMax \u6E20\u9053\u62A5\u8868\uFF08GET .../pmax/campaigns/reports/channels\uFF09")
|
|
126493
|
+
).action(
|
|
126494
|
+
async (opts) => {
|
|
126495
|
+
await runAdPmaxReportChannels({
|
|
126496
|
+
account: opts.account,
|
|
126497
|
+
startDate: opts.start,
|
|
126498
|
+
endDate: opts.end,
|
|
126499
|
+
campaignId: opts.campaignId,
|
|
126500
|
+
token: opts.token,
|
|
126501
|
+
jsonOut: opts.jsonOut,
|
|
126502
|
+
verbose: opts.verbose
|
|
126503
|
+
});
|
|
126504
|
+
}
|
|
126505
|
+
);
|
|
125857
126506
|
pmaxReportOpts(
|
|
125858
126507
|
adCmd.command("pmax-report-geo").description("PMax \u5730\u7406\u62A5\u8868 \u6D3B\u52A8\xD7\u56FD\u5BB6\uFF08GET .../pmax/campaigns/reports/geo\uFF09").option("--cost-greater <n>", "\u82B1\u8D39\u8FC7\u6EE4", (v) => parseFloat(v)).option("--click-greater <n>", "\u70B9\u51FB\u8FC7\u6EE4", (v) => parseFloat(v)).option("--conversions-greater <n>", "\u8F6C\u5316\u8FC7\u6EE4", (v) => parseFloat(v))
|
|
125859
126508
|
).action(
|
|
@@ -128015,6 +128664,8 @@ async function runMetaAdFormCreate(opts) {
|
|
|
128015
128664
|
init_xlsx_style_engine();
|
|
128016
128665
|
import fs12 from "fs";
|
|
128017
128666
|
import path17 from "path";
|
|
128667
|
+
init_html();
|
|
128668
|
+
init_lang();
|
|
128018
128669
|
var PENDING = "[\u5F85\u8865]";
|
|
128019
128670
|
var SHEET_NAMES = ["\u65B9\u6848\u603B\u89C8", "1-\u5BA2\u6237\u753B\u50CF", "2-\u8D26\u6237\u7ED3\u6784", "3-\u8868\u5355\u8BE2\u76D8C1"];
|
|
128020
128671
|
var OPS = {
|
|
@@ -128035,6 +128686,9 @@ var QUESTION_TYPE_LABEL = {
|
|
|
128035
128686
|
JOB_TITLE: "Job Title",
|
|
128036
128687
|
CUSTOM: "Custom"
|
|
128037
128688
|
};
|
|
128689
|
+
function chrome(text3, lang) {
|
|
128690
|
+
return lang === "en" ? applyEnglishPhrases(text3) : text3;
|
|
128691
|
+
}
|
|
128038
128692
|
function text2(value) {
|
|
128039
128693
|
if (value == null) return PENDING;
|
|
128040
128694
|
const s = String(value).trim();
|
|
@@ -128149,12 +128803,13 @@ function resolveCopyBlocks(cfg) {
|
|
|
128149
128803
|
}
|
|
128150
128804
|
return blocks;
|
|
128151
128805
|
}
|
|
128152
|
-
function writeOpsExcel(outPath, cfg) {
|
|
128806
|
+
function writeOpsExcel(outPath, cfg, lang = "zh") {
|
|
128153
128807
|
const plan = cfg.plan ?? {};
|
|
128154
128808
|
const wb = createExcelWorkbook({ accent: "1F4E79" });
|
|
128155
128809
|
const adSets = resolveAdSets(cfg);
|
|
128156
128810
|
const subtitle = defaultSubtitle(cfg);
|
|
128157
|
-
const
|
|
128811
|
+
const sheet = (index) => chrome(SHEET_NAMES[index], lang);
|
|
128812
|
+
const overview = wb.addSheet(sheet(0));
|
|
128158
128813
|
overview.setColWidths([20, 18, 18, 18, 18, 42]);
|
|
128159
128814
|
overview.titleBar(overviewTitle(plan), {
|
|
128160
128815
|
fill: null,
|
|
@@ -128163,22 +128818,22 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128163
128818
|
hAlign: "center"
|
|
128164
128819
|
});
|
|
128165
128820
|
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"), {
|
|
128821
|
+
overview.kvRow(chrome("\u5BA2\u6237\u540D\u79F0", lang), text2(plan.customerName));
|
|
128822
|
+
overview.kvRow(chrome("Facebook \u4E3B\u9875", lang), text2(plan.pageUrl || chrome("\u5F85 pages \u540E\u8865", lang)), {
|
|
128168
128823
|
hyperlink: plan.pageUrl?.startsWith("http") ? plan.pageUrl : void 0
|
|
128169
128824
|
});
|
|
128170
|
-
overview.kvRow("\u5B98\u65B9\u7F51\u7AD9", text2(plan.siteUrl), {
|
|
128825
|
+
overview.kvRow(chrome("\u5B98\u65B9\u7F51\u7AD9", lang), text2(plan.siteUrl), {
|
|
128171
128826
|
hyperlink: plan.siteUrl?.startsWith("http") ? plan.siteUrl : void 0
|
|
128172
128827
|
});
|
|
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(
|
|
128828
|
+
overview.kvRow(chrome("\u4E3B\u8425\u4E1A\u52A1", lang), text2(plan.businessOneLiner));
|
|
128829
|
+
overview.kvRow(chrome("\u6838\u5FC3\u4EA7\u54C1", lang), text2(plan.products));
|
|
128830
|
+
overview.kvRow(chrome("\u6838\u5FC3\u5356\u70B9", lang), text2(plan.sellingPoints));
|
|
128831
|
+
overview.kvRow(chrome("\u76EE\u6807\u5E02\u573A", lang), text2(plan.targetMarkets || joinList(cfg.adset?.countries, ", ")));
|
|
128832
|
+
overview.kvRow(chrome("\u8425\u9500\u76EE\u6807", lang), text2(plan.mainResult || chrome("\u8868\u5355\u8BE2\u76D8\uFF08Lead Form\uFF09", lang)));
|
|
128833
|
+
overview.kvRow(chrome("\u65E5\u9884\u7B97", lang), dailyBudgetText(cfg));
|
|
128834
|
+
overview.kvRow(chrome("\u5E7F\u544A\u7ED3\u6784", lang), structureSummary(cfg));
|
|
128835
|
+
overview.kvRow(chrome("\u6295\u653E\u7B56\u7565", lang), text2(plan.strategy || plan.landingType));
|
|
128836
|
+
const profile = wb.addSheet(sheet(1));
|
|
128182
128837
|
profile.setColWidths([26, 48, 26, 26]);
|
|
128183
128838
|
profile.titleBar(profileTitle(plan), { fill: OPS.title });
|
|
128184
128839
|
profile.subtitleBar(subtitle);
|
|
@@ -128220,7 +128875,7 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128220
128875
|
profile.noteRow(
|
|
128221
128876
|
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
128877
|
);
|
|
128223
|
-
const structure = wb.addSheet(
|
|
128878
|
+
const structure = wb.addSheet(sheet(2));
|
|
128224
128879
|
structure.setColWidths([18, 44, 26, 22]);
|
|
128225
128880
|
structure.titleBar(text2(plan.brand ? `\u5E7F\u544A\u8D26\u6237\u7ED3\u6784\uFF1A${plan.brand}` : "\u5E7F\u544A\u8D26\u6237\u7ED3\u6784"), {
|
|
128226
128881
|
fill: OPS.title
|
|
@@ -128259,7 +128914,7 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128259
128914
|
structure.noteRow(
|
|
128260
128915
|
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
128916
|
);
|
|
128262
|
-
const lead = wb.addSheet(
|
|
128917
|
+
const lead = wb.addSheet(sheet(3));
|
|
128263
128918
|
lead.setColWidths([16, 22, 36, 40, 16, 18]);
|
|
128264
128919
|
lead.titleBar(`Campaign 1\uFF1A\u8868\u5355\u8BE2\u76D8\uFF08Leads\uFF09\uFF5C ${dailyBudgetText(cfg)}`, { fill: OPS.title });
|
|
128265
128920
|
lead.subtitleBar(subtitle);
|
|
@@ -128313,7 +128968,7 @@ function writeOpsExcel(outPath, cfg) {
|
|
|
128313
128968
|
}
|
|
128314
128969
|
return wb.writeFile(outPath);
|
|
128315
128970
|
}
|
|
128316
|
-
function renderMarkdown(cfg) {
|
|
128971
|
+
function renderMarkdown(cfg, lang = "zh") {
|
|
128317
128972
|
const plan = cfg.plan ?? {};
|
|
128318
128973
|
const adSets = resolveAdSets(cfg);
|
|
128319
128974
|
const questions = (cfg.form?.questions ?? []).map(
|
|
@@ -128325,13 +128980,14 @@ function renderMarkdown(cfg) {
|
|
|
128325
128980
|
|
|
128326
128981
|
${text2(block.text)}
|
|
128327
128982
|
`).join("\n");
|
|
128983
|
+
const h = (label2) => chrome(label2, lang);
|
|
128328
128984
|
return `# ${overviewTitle(plan)}
|
|
128329
128985
|
|
|
128330
|
-
- \u5BA2\u6237
|
|
128331
|
-
- \
|
|
128986
|
+
- ${h("\u5BA2\u6237\u540D\u79F0")}/${h("\u5B98\u65B9\u7F51\u7AD9")}\uFF1A${text2(plan.customerName)} + ${text2(plan.siteUrl)} + ${text2(plan.businessOneLiner)}
|
|
128987
|
+
- ${h("\u8425\u9500\u76EE\u6807")}\uFF1A${text2(plan.mainResult)}
|
|
128332
128988
|
- \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)}
|
|
128989
|
+
- ${h("\u65E5\u9884\u7B97")}\uFF1A${dailyBudgetText(cfg)}\u3000${h("\u56FD\u5BB6")}\uFF1A${joinList(cfg.adset?.countries, ", ")}
|
|
128990
|
+
- ${h("\u5E7F\u544A\u7ED3\u6784")}\uFF1A${structureSummary(cfg)}
|
|
128335
128991
|
- \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
128992
|
|
|
128337
128993
|
> \u8D26\u6237\uFF1A${text2(cfg.account)}\u3000\u4E3B\u9875\uFF1A${text2(cfg.pageId)}
|
|
@@ -128391,24 +129047,25 @@ ${copies}
|
|
|
128391
129047
|
\u8349\u6848\u4F9D\u636E\u4E3A\u516C\u5F00\u9875\u9762/\u5BA2\u6237\u6750\u6599\uFF0C\u975E\u5E7F\u544A\u540E\u53F0\u6570\u636E\u3002
|
|
128392
129048
|
`;
|
|
128393
129049
|
}
|
|
128394
|
-
function writeMetaLeadPlanExcel(outPath, cfg) {
|
|
128395
|
-
return writeOpsExcel(outPath, cfg);
|
|
129050
|
+
function writeMetaLeadPlanExcel(outPath, cfg, lang = "zh") {
|
|
129051
|
+
return writeOpsExcel(outPath, cfg, lang);
|
|
128396
129052
|
}
|
|
128397
|
-
function writeMetaLeadPlanMarkdown(outPath, cfg) {
|
|
129053
|
+
function writeMetaLeadPlanMarkdown(outPath, cfg, lang = "zh") {
|
|
128398
129054
|
const abs = path17.resolve(outPath);
|
|
128399
129055
|
fs12.mkdirSync(path17.dirname(abs), { recursive: true });
|
|
128400
|
-
fs12.writeFileSync(abs, renderMarkdown(cfg), "utf8");
|
|
129056
|
+
fs12.writeFileSync(abs, renderMarkdown(cfg, lang), "utf8");
|
|
128401
129057
|
return abs;
|
|
128402
129058
|
}
|
|
128403
129059
|
async function runMetaAdPlanRender(opts) {
|
|
128404
129060
|
const cfg = loadMetaLeadCreateConfig(opts.configFile);
|
|
129061
|
+
const lang = readReportLangOrExit({ flag: opts.lang });
|
|
128405
129062
|
const configDir = path17.dirname(path17.resolve(opts.configFile));
|
|
128406
129063
|
const xlsxOut = path17.resolve(opts.out || path17.join(configDir, "meta-lead-plan.xlsx"));
|
|
128407
129064
|
const mdOut = path17.resolve(
|
|
128408
129065
|
opts.mdOut || path17.join(path17.dirname(xlsxOut), `${path17.parse(xlsxOut).name}.md`)
|
|
128409
129066
|
);
|
|
128410
|
-
const xlsxPath = writeMetaLeadPlanExcel(xlsxOut, cfg);
|
|
128411
|
-
const mdPath = writeMetaLeadPlanMarkdown(mdOut, cfg);
|
|
129067
|
+
const xlsxPath = writeMetaLeadPlanExcel(xlsxOut, cfg, lang);
|
|
129068
|
+
const mdPath = writeMetaLeadPlanMarkdown(mdOut, cfg, lang);
|
|
128412
129069
|
console.log(
|
|
128413
129070
|
JSON.stringify({
|
|
128414
129071
|
ok: true,
|
|
@@ -129196,7 +129853,7 @@ function register22(program2) {
|
|
|
129196
129853
|
await runMetaAdCreate(opts);
|
|
129197
129854
|
}
|
|
129198
129855
|
);
|
|
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) => {
|
|
129856
|
+
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
129857
|
await runMetaAdPlanRender(opts);
|
|
129201
129858
|
});
|
|
129202
129859
|
addCommon(addAccount(meta.command("account").description("\u8BFB\u5E7F\u544A\u8D26\u6237\uFF08\u4F59\u989D/\u82B1\u8D39/\u5E01\u79CD\uFF09"))).action(
|
|
@@ -134470,6 +135127,8 @@ async function runWebsiteDiagnosisPrepare(opts) {
|
|
|
134470
135127
|
}
|
|
134471
135128
|
|
|
134472
135129
|
// src/commands/website-diagnosis/render-report.ts
|
|
135130
|
+
init_lang();
|
|
135131
|
+
init_html();
|
|
134473
135132
|
import fs16 from "fs";
|
|
134474
135133
|
import fsPromises from "fs/promises";
|
|
134475
135134
|
import path21 from "path";
|
|
@@ -134521,13 +135180,14 @@ function mergeCollectLighthouse(data, collect) {
|
|
|
134521
135180
|
...collect.lighthouseWarning && !data.lighthouseWarning ? { lighthouseWarning: collect.lighthouseWarning } : {}
|
|
134522
135181
|
};
|
|
134523
135182
|
}
|
|
134524
|
-
function injectReportData(html, payload) {
|
|
134525
|
-
const
|
|
135183
|
+
function injectReportData(html, payload, lang) {
|
|
135184
|
+
const localized = localizeReportHtml(html, lang);
|
|
135185
|
+
const json = JSON.stringify(stampMetaLang(payload, lang)).replace(/</g, "\\u003c");
|
|
134526
135186
|
const marker = "window.__WEBSITE_DIAGNOSIS__ = window.__WEBSITE_DIAGNOSIS__ || null;";
|
|
134527
|
-
if (!
|
|
135187
|
+
if (!localized.includes(marker)) {
|
|
134528
135188
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 website-diagnosis-report.html");
|
|
134529
135189
|
}
|
|
134530
|
-
return
|
|
135190
|
+
return localized.replace(marker, `window.__WEBSITE_DIAGNOSIS__ = ${json};`);
|
|
134531
135191
|
}
|
|
134532
135192
|
async function runWebsiteDiagnosisRender(opts) {
|
|
134533
135193
|
const dataPath = path21.resolve(opts.dataFile);
|
|
@@ -134537,6 +135197,7 @@ async function runWebsiteDiagnosisRender(opts) {
|
|
|
134537
135197
|
const collectRaw = await readJsonFile(path21.resolve(opts.collectFile));
|
|
134538
135198
|
data = mergeCollectLighthouse(data, asRecord5(collectRaw));
|
|
134539
135199
|
}
|
|
135200
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
134540
135201
|
const templatePath = websiteDiagnosisReportTemplatePath();
|
|
134541
135202
|
let html;
|
|
134542
135203
|
try {
|
|
@@ -134553,7 +135214,7 @@ async function runWebsiteDiagnosisRender(opts) {
|
|
|
134553
135214
|
);
|
|
134554
135215
|
const outDir = path21.dirname(outPath);
|
|
134555
135216
|
await fsPromises.mkdir(outDir, { recursive: true });
|
|
134556
|
-
await fsPromises.writeFile(outPath, injectReportData(html, data), "utf8");
|
|
135217
|
+
await fsPromises.writeFile(outPath, injectReportData(html, data, lang), "utf8");
|
|
134557
135218
|
const runtimeSrc = websiteDiagnosisRuntimePath();
|
|
134558
135219
|
const runtimeOut = path21.join(outDir, TEMPLATE_BASENAMES.runtime);
|
|
134559
135220
|
let runtimeCopied = false;
|
|
@@ -134620,11 +135281,12 @@ function registerWebsiteDiagnosisCommands(program2) {
|
|
|
134620
135281
|
jsonOut: opts.jsonOut
|
|
134621
135282
|
});
|
|
134622
135283
|
});
|
|
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) => {
|
|
135284
|
+
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
135285
|
await runWebsiteDiagnosisRender({
|
|
134625
135286
|
dataFile: opts.data,
|
|
134626
135287
|
collectFile: opts.collect,
|
|
134627
|
-
out: opts.out
|
|
135288
|
+
out: opts.out,
|
|
135289
|
+
lang: opts.lang
|
|
134628
135290
|
});
|
|
134629
135291
|
});
|
|
134630
135292
|
}
|
|
@@ -134980,12 +135642,12 @@ function countTableColumns(tableHtml) {
|
|
|
134980
135642
|
return Math.max(th, td);
|
|
134981
135643
|
}
|
|
134982
135644
|
function isCompareTable(tableHtml, html, tableIndex) {
|
|
134983
|
-
const inTable =
|
|
135645
|
+
const inTable = /对比|竞品|功能|性能|维度|指标|参数|competitor|compare|feature/i.test(tableHtml);
|
|
134984
135646
|
if (inTable) return true;
|
|
134985
135647
|
const windowStart = Math.max(0, tableIndex - 600);
|
|
134986
135648
|
const windowEnd = Math.min(html.length, tableIndex + tableHtml.length + 400);
|
|
134987
135649
|
const nearby = html.slice(windowStart, windowEnd);
|
|
134988
|
-
return
|
|
135650
|
+
return /对比|竞品|竞争|功能|性能|对标|competitor|compare|benchmark/i.test(nearby);
|
|
134989
135651
|
}
|
|
134990
135652
|
function findFeatureCompareTableRows(html) {
|
|
134991
135653
|
const tables = html.match(/<table[\s\S]*?<\/table>/gi) ?? [];
|
|
@@ -135002,9 +135664,9 @@ function findFeatureCompareTableRows(html) {
|
|
|
135002
135664
|
return best;
|
|
135003
135665
|
}
|
|
135004
135666
|
function countPainPoints(html) {
|
|
135005
|
-
const labeled = (html.match(
|
|
135667
|
+
const labeled = (html.match(/(?:痛点|pain\s*point)\s*\d/gi) ?? []).length;
|
|
135006
135668
|
if (labeled >= 4) return labeled;
|
|
135007
|
-
const section = html.match(
|
|
135669
|
+
const section = html.match(/(?:痛点|pain points?)[\s\S]{0,3000}/i)?.[0] ?? html;
|
|
135008
135670
|
const listItems = (section.match(/<li[^>]*>/gi) ?? []).length;
|
|
135009
135671
|
return Math.max(labeled, listItems >= 4 ? 4 : listItems);
|
|
135010
135672
|
}
|
|
@@ -135020,7 +135682,7 @@ function hasEchartsInlineResize(html) {
|
|
|
135020
135682
|
return /addEventListener\s*\(\s*['"]resize['"]/.test(html) && /\.resize\s*\(/.test(html);
|
|
135021
135683
|
}
|
|
135022
135684
|
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] ?? "";
|
|
135685
|
+
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
135686
|
if (competitorSection) {
|
|
135025
135687
|
const listItems = (competitorSection.match(/<li[^>]*>[\s\S]*?<\/li>/gi) ?? []).filter(
|
|
135026
135688
|
(li) => stripHtmlTags(li).trim().length >= 2
|
|
@@ -135061,8 +135723,10 @@ function splitMarketTokens(value) {
|
|
|
135061
135723
|
return value.split(/[、,,/|]/).map((t) => t.trim()).filter((t) => t.length >= 2);
|
|
135062
135724
|
}
|
|
135063
135725
|
function hasTargetGeoBreakdown(html, ctx) {
|
|
135064
|
-
const hasMetrics = /规模|增长|优先级|潜力|份额|CAGR
|
|
135065
|
-
|
|
135726
|
+
const hasMetrics = /规模|增长|优先级|潜力|份额|CAGR|市场容量|market size|growth|priority|share/i.test(
|
|
135727
|
+
html
|
|
135728
|
+
);
|
|
135729
|
+
const hasGeoFrame = /国家|区域|地区|市场|country|region|market/i.test(html);
|
|
135066
135730
|
if (!hasMetrics || !hasGeoFrame) return false;
|
|
135067
135731
|
const targetMarket = ctx.targetMarket?.trim() ?? "";
|
|
135068
135732
|
if (targetMarket) {
|
|
@@ -135079,56 +135743,58 @@ function hasTargetGeoBreakdown(html, ctx) {
|
|
|
135079
135743
|
return regionHits >= 2;
|
|
135080
135744
|
}
|
|
135081
135745
|
function hasReportTitle(html, ctx) {
|
|
135082
|
-
const hasTitle = /战略市场分析|KA
|
|
135746
|
+
const hasTitle = /战略市场分析|KA客户|行业分析报告|市场分析报告|行业调查|市场调查|industry analysis|market analysis|strategic market/i.test(
|
|
135747
|
+
html
|
|
135748
|
+
);
|
|
135083
135749
|
if (!hasTitle) return false;
|
|
135084
135750
|
return /目标市场|全球市场|行业|细分|market/i.test(html) || !!ctx.targetMarket?.trim() || !!ctx.industry?.trim() || !!ctx.customerName?.trim();
|
|
135085
135751
|
}
|
|
135086
135752
|
var CONTENT_RULES = [
|
|
135087
135753
|
{ id: "cover", test: (h, ctx) => hasReportTitle(h, ctx) },
|
|
135088
135754
|
{ id: "cover-kpi", test: (h) => /核心结论|metric|kpi|结论|摘要|executive summary/i.test(h) },
|
|
135089
|
-
{ id: "ch1", test: (h) =>
|
|
135755
|
+
{ id: "ch1", test: (h) => /市场与趋势诊断|market and trend/i.test(h) },
|
|
135090
135756
|
{
|
|
135091
135757
|
id: "ch1-tam",
|
|
135092
|
-
test: (h) => (/TAM|SAM|SOM/.test(h) ||
|
|
135758
|
+
test: (h) => (/TAM|SAM|SOM/.test(h) || /市场规模|market size/i.test(h)) && /CAGR|增长率|增长趋势|growth/i.test(h)
|
|
135093
135759
|
},
|
|
135094
|
-
{ id: "ch1-value-chain", test: (h) =>
|
|
135760
|
+
{ id: "ch1-value-chain", test: (h) => /价值链|生态定位|产业链|value chain|ecosystem/i.test(h) },
|
|
135095
135761
|
{ 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) =>
|
|
135762
|
+
{ id: "ch1-pestel", test: (h) => /PESTEL|政策|法规环境|技术趋势|经济|社会|环境|policy|regulatory/i.test(h) },
|
|
135763
|
+
{ id: "ch1-forecast", test: (h) => /预测|3.?5年|未来\d|forecast|next \d/i.test(h) },
|
|
135764
|
+
{ id: "ch2", test: (h) => /行业深度洞察|目标行业|industry insight|target industry/i.test(h) },
|
|
135099
135765
|
{ id: "ch2-pain", test: (h, ctx) => ctx.painPointCount >= 4 },
|
|
135100
|
-
{ id: "ch2-compliance", test: (h) =>
|
|
135766
|
+
{ id: "ch2-compliance", test: (h) => /法规|合规|regulation|compliance/i.test(h) && /<table/.test(h) },
|
|
135101
135767
|
{
|
|
135102
135768
|
id: "ch2-bpmn",
|
|
135103
|
-
test: (h) => /原流程|BPMN
|
|
135769
|
+
test: (h) => /原流程|BPMN|介入后|新流程|as-is|to-be|current process/i.test(h) && /效率|成本|提升|下降|节约|efficiency|cost|improve/i.test(h)
|
|
135104
135770
|
},
|
|
135105
|
-
{ id: "ch3", test: (h) =>
|
|
135106
|
-
{ id: "ch3-audience", test: (h) =>
|
|
135107
|
-
{ id: "ch3-scenario", test: (h) =>
|
|
135108
|
-
{ id: "ch4", test: (h) => /竞争策略|竞争.{0,6}
|
|
135771
|
+
{ id: "ch3", test: (h) => /目标受众|受众与场景|target audience|audience and scenario/i.test(h) },
|
|
135772
|
+
{ id: "ch3-audience", test: (h) => /用户|受众|画像|群体|audience|persona|segment/i.test(h) && /<table/.test(h) },
|
|
135773
|
+
{ id: "ch3-scenario", test: (h) => /应用场景|场景|差异化|用户价值|企业价值|use case|scenario/i.test(h) },
|
|
135774
|
+
{ id: "ch4", test: (h) => /竞争策略|竞争.{0,6}定位|competitive (strategy|positioning)/i.test(h) },
|
|
135109
135775
|
{ id: "ch4-competitors", test: (h, ctx) => ctx.competitorCount >= 3 },
|
|
135110
135776
|
{ id: "ch4-compare-table", test: (h, ctx) => ctx.competitorTableRows >= 11 },
|
|
135111
135777
|
{
|
|
135112
135778
|
id: "ch4-gaps",
|
|
135113
135779
|
test: (h) => [
|
|
135114
|
-
|
|
135115
|
-
|
|
135116
|
-
|
|
135117
|
-
|
|
135780
|
+
/功能空白|功能.*空白|feature gap/i.test(h),
|
|
135781
|
+
/场景|scenario/i.test(h),
|
|
135782
|
+
/用户群|用户|audience|segment/i.test(h),
|
|
135783
|
+
/地域|地区|区域|geo|region/i.test(h)
|
|
135118
135784
|
].filter(Boolean).length >= 3
|
|
135119
135785
|
},
|
|
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) =>
|
|
135786
|
+
{ id: "ch4-positioning", test: (h) => /定位陈述|定位:|核心定位|差异化|positioning|differentiat/i.test(h) },
|
|
135787
|
+
{ id: "ch5", test: (h) => /增长与品牌|GTM|growth and brand/i.test(h) },
|
|
135788
|
+
{ id: "ch5-gtm", test: (h) => /试点|规模复制|生态扩展|三阶段|pilot|scale|three phases/i.test(h) && /KPI|ROI|指标|metric/i.test(h) },
|
|
135789
|
+
{ id: "ch5-brand", test: (h) => /品牌|传播|主张|brand|message/i.test(h) },
|
|
135790
|
+
{ id: "ch5-tactics", test: (h) => /内容营销|渠道|KOL|销售模式|营销|content marketing|channel/i.test(h) },
|
|
135791
|
+
{ id: "ch6", test: (h) => /实施|implementation/i.test(h) && /风险|资源|risk|resource/i.test(h) },
|
|
135792
|
+
{ id: "ch6-milestone", test: (h) => /里程碑|阶段|milestone|phase/i.test(h) && /任务|负责人|成果|指标|owner|deliverable/i.test(h) },
|
|
135793
|
+
{ id: "ch6-budget", test: (h) => /预算|资源需求|人力|分配|budget|headcount/i.test(h) },
|
|
135794
|
+
{ id: "ch6-risk", test: (h) => /风险|risk/i.test(h) && /应对|措施|矩阵|mitigation|matrix/i.test(h) },
|
|
135795
|
+
{ id: "appendix", test: (h) => /附录|数据来源|appendix|sources/i.test(h) },
|
|
135796
|
+
{ id: "appendix-sources", test: (h) => /数据来源|Source:|报告名称|发布日期|http/i.test(h) },
|
|
135797
|
+
{ id: "appendix-methods", test: (h) => /调研方法|桌面研究|访谈|问卷|desk research|interview|survey/i.test(h) },
|
|
135132
135798
|
{
|
|
135133
135799
|
id: "appendix-glossary",
|
|
135134
135800
|
test: (h) => [/ROI/.test(h), /CAGR/.test(h), /GTM/.test(h), /BPMN/.test(h)].filter(Boolean).length >= 3
|
|
@@ -135193,6 +135859,7 @@ function formatMarketReportContentErrors(result) {
|
|
|
135193
135859
|
}
|
|
135194
135860
|
|
|
135195
135861
|
// src/commands/market-analysis/render-report.ts
|
|
135862
|
+
init_lang();
|
|
135196
135863
|
function asRecord6(value) {
|
|
135197
135864
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
135198
135865
|
return value;
|
|
@@ -135236,6 +135903,16 @@ async function runMarketAnalysisRender(opts) {
|
|
|
135236
135903
|
process.exit(1);
|
|
135237
135904
|
}
|
|
135238
135905
|
const reportData = asRecord6(dataRaw);
|
|
135906
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: reportData.meta });
|
|
135907
|
+
try {
|
|
135908
|
+
assertHtmlLangMatches(html, lang);
|
|
135909
|
+
} catch (err) {
|
|
135910
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
135911
|
+
console.error(`
|
|
135912
|
+
\u274C ${message}
|
|
135913
|
+
`);
|
|
135914
|
+
process.exit(1);
|
|
135915
|
+
}
|
|
135239
135916
|
const contentCheck = validateMarketReportContent(html, validationContextFromReport(reportData));
|
|
135240
135917
|
if (!contentCheck.ok) {
|
|
135241
135918
|
console.error(`
|
|
@@ -135287,10 +135964,11 @@ function registerMarketAnalysisCommands(program2) {
|
|
|
135287
135964
|
});
|
|
135288
135965
|
}
|
|
135289
135966
|
);
|
|
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) => {
|
|
135967
|
+
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
135968
|
await runMarketAnalysisRender({
|
|
135292
135969
|
dataFile: opts.data,
|
|
135293
|
-
out: opts.out
|
|
135970
|
+
out: opts.out,
|
|
135971
|
+
lang: opts.lang
|
|
135294
135972
|
});
|
|
135295
135973
|
});
|
|
135296
135974
|
}
|
|
@@ -137467,6 +138145,8 @@ function applyDataRenderedCopy(data) {
|
|
|
137467
138145
|
}
|
|
137468
138146
|
|
|
137469
138147
|
// src/commands/google-ads-diagnosis/render-report.ts
|
|
138148
|
+
init_lang();
|
|
138149
|
+
init_html();
|
|
137470
138150
|
function asRecord16(value) {
|
|
137471
138151
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
137472
138152
|
return value;
|
|
@@ -137590,9 +138270,10 @@ async function runGoogleAdsDiagnosisRender(opts) {
|
|
|
137590
138270
|
`);
|
|
137591
138271
|
process.exit(1);
|
|
137592
138272
|
}
|
|
138273
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
137593
138274
|
let rendered;
|
|
137594
138275
|
try {
|
|
137595
|
-
rendered = injectGoogleAdsDiagnosisData(html, data);
|
|
138276
|
+
rendered = injectGoogleAdsDiagnosisData(localizeReportHtml(html, lang), stampMetaLang(data, lang));
|
|
137596
138277
|
} catch (err) {
|
|
137597
138278
|
const message = err instanceof Error ? err.message : String(err);
|
|
137598
138279
|
console.error(`
|
|
@@ -137656,14 +138337,15 @@ function registerGoogleAdsDiagnosisCommands(program2) {
|
|
|
137656
138337
|
"--no-merge-collect",
|
|
137657
138338
|
"\u4E0D\u4ECE collect \u81EA\u52A8\u6062\u590D campaigns/geographic/keywords.items",
|
|
137658
138339
|
false
|
|
137659
|
-
).option("--lenient", "\u7ED3\u6784\u8B66\u544A\uFF08\u5982\u7F3A analysis\uFF09\u65F6\u4E0D\u963B\u65AD\u6E32\u67D3", false).action(
|
|
138340
|
+
).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
138341
|
async (opts) => {
|
|
137661
138342
|
await runGoogleAdsDiagnosisRender({
|
|
137662
138343
|
dataFile: opts.data,
|
|
137663
138344
|
out: opts.out,
|
|
137664
138345
|
collectFile: opts.collect,
|
|
137665
138346
|
noMergeCollect: opts.noMergeCollect,
|
|
137666
|
-
lenient: opts.lenient
|
|
138347
|
+
lenient: opts.lenient,
|
|
138348
|
+
lang: opts.lang
|
|
137667
138349
|
});
|
|
137668
138350
|
}
|
|
137669
138351
|
);
|
|
@@ -138044,15 +138726,27 @@ function utcToIso(ms) {
|
|
|
138044
138726
|
const d = new Date(ms);
|
|
138045
138727
|
return isoDate(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
|
|
138046
138728
|
}
|
|
138047
|
-
function reportPeriodChrome(current, previous) {
|
|
138048
|
-
const kind = classifyReportPeriod(current, previous);
|
|
138729
|
+
function reportPeriodChrome(current, previous, lang = "zh") {
|
|
138730
|
+
const kind = classifyReportPeriod(current, previous, lang);
|
|
138049
138731
|
if (kind.unit === "\u5B63\u5EA6") {
|
|
138050
|
-
return {
|
|
138732
|
+
return {
|
|
138733
|
+
...kind,
|
|
138734
|
+
reportTitle: lang === "en" ? "Google quarterly business report" : "Google \u5B63\u5EA6\u7ECF\u8425\u62A5\u544A",
|
|
138735
|
+
coverEn: "QUARTERLY REPORT"
|
|
138736
|
+
};
|
|
138051
138737
|
}
|
|
138052
138738
|
if (kind.unit === "\u6708\u5EA6") {
|
|
138053
|
-
return {
|
|
138739
|
+
return {
|
|
138740
|
+
...kind,
|
|
138741
|
+
reportTitle: lang === "en" ? "Google monthly business report" : "Google \u6708\u5EA6\u7ECF\u8425\u62A5\u544A",
|
|
138742
|
+
coverEn: "MONTHLY REPORT"
|
|
138743
|
+
};
|
|
138054
138744
|
}
|
|
138055
|
-
return {
|
|
138745
|
+
return {
|
|
138746
|
+
...kind,
|
|
138747
|
+
reportTitle: lang === "en" ? "Google business report" : "Google \u7ECF\u8425\u62A5\u544A",
|
|
138748
|
+
coverEn: "PERFORMANCE REPORT"
|
|
138749
|
+
};
|
|
138056
138750
|
}
|
|
138057
138751
|
function lastCompleteQuarter(now = /* @__PURE__ */ new Date()) {
|
|
138058
138752
|
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
@@ -138892,6 +139586,8 @@ import { fileURLToPath as fileURLToPath8 } from "url";
|
|
|
138892
139586
|
var TSO_CLI_ROOT = path31.join(path31.dirname(fileURLToPath8(import.meta.url)), "../..");
|
|
138893
139587
|
|
|
138894
139588
|
// src/commands/google-quarterly/render-report.ts
|
|
139589
|
+
init_lang();
|
|
139590
|
+
init_html();
|
|
138895
139591
|
function asRecord18(value) {
|
|
138896
139592
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
138897
139593
|
return value;
|
|
@@ -138941,8 +139637,16 @@ async function runGoogleQuarterlyRender(opts) {
|
|
|
138941
139637
|
}
|
|
138942
139638
|
const outPath = path32.resolve(opts.out ?? path32.join(path32.dirname(dataPath), GOOGLE_QUARTERLY_HTML_BASENAME));
|
|
138943
139639
|
await fs27.mkdir(path32.dirname(outPath), { recursive: true });
|
|
138944
|
-
const
|
|
138945
|
-
const
|
|
139640
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: merged.meta });
|
|
139641
|
+
const periodChrome = reportPeriodChrome(
|
|
139642
|
+
readMetaRange(merged, "current"),
|
|
139643
|
+
readMetaRange(merged, "previous"),
|
|
139644
|
+
lang
|
|
139645
|
+
);
|
|
139646
|
+
const outHtml = injectQuarterlyReport(
|
|
139647
|
+
localizeReportHtml(html, lang),
|
|
139648
|
+
stampMetaLang({ ...merged, periodChrome }, lang)
|
|
139649
|
+
);
|
|
138946
139650
|
if (!outHtml.includes("homeCDN/echarts.min.js") || /new Chart\s*\(/.test(outHtml)) {
|
|
138947
139651
|
console.error("\n\u274C \u6A21\u677F\u5FC5\u987B\u4F7F\u7528 ECharts\uFF0C\u7981\u6B62 Chart.js\u3002\n");
|
|
138948
139652
|
process.exit(1);
|
|
@@ -138994,14 +139698,15 @@ function registerGoogleQuarterlyCommands(program2) {
|
|
|
138994
139698
|
});
|
|
138995
139699
|
}
|
|
138996
139700
|
);
|
|
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);
|
|
139701
|
+
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
139702
|
render.action(
|
|
138999
139703
|
async (opts) => {
|
|
139000
139704
|
await runGoogleQuarterlyRender({
|
|
139001
139705
|
dataFile: opts.data,
|
|
139002
139706
|
collectFile: opts.collect,
|
|
139003
139707
|
out: opts.out,
|
|
139004
|
-
lenient: opts.lenient
|
|
139708
|
+
lenient: opts.lenient,
|
|
139709
|
+
lang: opts.lang
|
|
139005
139710
|
});
|
|
139006
139711
|
}
|
|
139007
139712
|
);
|
|
@@ -139412,6 +140117,9 @@ async function mergeFacebookSnapshotIntoReport(payload, snapshotDir) {
|
|
|
139412
140117
|
};
|
|
139413
140118
|
}
|
|
139414
140119
|
|
|
140120
|
+
// src/commands/facebook-analysis/render-excel.ts
|
|
140121
|
+
init_html();
|
|
140122
|
+
|
|
139415
140123
|
// src/commands/facebook-analysis/write-xlsx.ts
|
|
139416
140124
|
init_xlsx_style_engine();
|
|
139417
140125
|
var MIN_COL_WIDTH = 10;
|
|
@@ -139620,8 +140328,18 @@ function buildMetaPeriodExcelSheets(data) {
|
|
|
139620
140328
|
{ name: "\u53D7\u4F17", rows: audienceRows }
|
|
139621
140329
|
];
|
|
139622
140330
|
}
|
|
139623
|
-
function
|
|
139624
|
-
|
|
140331
|
+
function chrome2(text3, lang) {
|
|
140332
|
+
return lang === "en" ? applyEnglishPhrases(text3) : text3;
|
|
140333
|
+
}
|
|
140334
|
+
function writeMetaPeriodExcel(outPath, data, lang = "zh") {
|
|
140335
|
+
const sheets = buildMetaPeriodExcelSheets(data).map((sheet) => ({
|
|
140336
|
+
...sheet,
|
|
140337
|
+
name: chrome2(sheet.name, lang),
|
|
140338
|
+
rows: sheet.rows.map(
|
|
140339
|
+
(row, index) => index === 0 ? row.map((cell5) => typeof cell5 === "string" ? chrome2(cell5, lang) : cell5) : row
|
|
140340
|
+
)
|
|
140341
|
+
}));
|
|
140342
|
+
writeSimpleXlsx(outPath, sheets);
|
|
139625
140343
|
}
|
|
139626
140344
|
|
|
139627
140345
|
// src/commands/facebook-analysis/report-content.ts
|
|
@@ -139911,6 +140629,8 @@ function formatMetaPeriodReportErrors(result) {
|
|
|
139911
140629
|
|
|
139912
140630
|
// src/commands/facebook-analysis/render-report.ts
|
|
139913
140631
|
init_report_period();
|
|
140632
|
+
init_lang();
|
|
140633
|
+
init_html();
|
|
139914
140634
|
var TEMPLATE_BASENAMES2 = {
|
|
139915
140635
|
html: "meta-period-report.html"
|
|
139916
140636
|
};
|
|
@@ -139959,12 +140679,13 @@ function asRecord27(value) {
|
|
|
139959
140679
|
}
|
|
139960
140680
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
139961
140681
|
}
|
|
139962
|
-
function injectReportData3(html, payload) {
|
|
139963
|
-
const
|
|
139964
|
-
|
|
140682
|
+
function injectReportData3(html, payload, lang) {
|
|
140683
|
+
const localized = localizeReportHtml(html, lang);
|
|
140684
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
140685
|
+
if (!localized.includes(INJECT_MARKER2)) {
|
|
139965
140686
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 meta-period-report.html");
|
|
139966
140687
|
}
|
|
139967
|
-
return
|
|
140688
|
+
return localized.replace(INJECT_MARKER2, `window.__META_PERIOD_REPORT__ = ${json};`);
|
|
139968
140689
|
}
|
|
139969
140690
|
function defaultOutPath(dataPath, format, out) {
|
|
139970
140691
|
if (out?.trim()) {
|
|
@@ -139987,6 +140708,7 @@ async function runFacebookAnalysisRender(opts) {
|
|
|
139987
140708
|
data = await mergeFacebookSnapshotIntoReport(data, path42.resolve(opts.snapshotDir));
|
|
139988
140709
|
}
|
|
139989
140710
|
localizeFacebookReportLabels(data);
|
|
140711
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
139990
140712
|
const contentCheck = validateMetaPeriodReportContent(data);
|
|
139991
140713
|
if (!contentCheck.ok) {
|
|
139992
140714
|
console.error(`
|
|
@@ -140005,7 +140727,7 @@ async function runFacebookAnalysisRender(opts) {
|
|
|
140005
140727
|
const outPath = defaultOutPath(dataPath, format, opts.out);
|
|
140006
140728
|
await fsPromises3.mkdir(path42.dirname(outPath), { recursive: true });
|
|
140007
140729
|
if (format === "xlsx") {
|
|
140008
|
-
writeMetaPeriodExcel(outPath, data);
|
|
140730
|
+
writeMetaPeriodExcel(outPath, data, lang);
|
|
140009
140731
|
} else {
|
|
140010
140732
|
const templatePath = metaPeriodReportTemplatePath();
|
|
140011
140733
|
let html;
|
|
@@ -140018,7 +140740,7 @@ async function runFacebookAnalysisRender(opts) {
|
|
|
140018
140740
|
`);
|
|
140019
140741
|
process.exit(1);
|
|
140020
140742
|
}
|
|
140021
|
-
await fsPromises3.writeFile(outPath, injectReportData3(html, data), "utf8");
|
|
140743
|
+
await fsPromises3.writeFile(outPath, injectReportData3(html, data, lang), "utf8");
|
|
140022
140744
|
}
|
|
140023
140745
|
written.push(outPath);
|
|
140024
140746
|
}
|
|
@@ -140389,6 +141111,8 @@ function formatMetaDiagnosisReportErrors(result) {
|
|
|
140389
141111
|
}
|
|
140390
141112
|
|
|
140391
141113
|
// src/commands/facebook-analysis/diagnosis-render-report.ts
|
|
141114
|
+
init_lang();
|
|
141115
|
+
init_html();
|
|
140392
141116
|
var TEMPLATE_BASENAME2 = "meta-account-diagnosis-report.html";
|
|
140393
141117
|
var INJECT_MARKER3 = "window.__META_DIAGNOSIS_REPORT__ = window.__META_DIAGNOSIS_REPORT__ || null;";
|
|
140394
141118
|
function resolveSkillTemplatePath5(basename13) {
|
|
@@ -140420,12 +141144,13 @@ function asRecord30(value) {
|
|
|
140420
141144
|
}
|
|
140421
141145
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
140422
141146
|
}
|
|
140423
|
-
function injectReportData4(html, payload) {
|
|
140424
|
-
const
|
|
140425
|
-
|
|
141147
|
+
function injectReportData4(html, payload, lang) {
|
|
141148
|
+
const localized = localizeReportHtml(html, lang);
|
|
141149
|
+
const json = JSON.stringify(stampMetaLang(payload, lang)).replace(/</g, "\\u003c");
|
|
141150
|
+
if (!localized.includes(INJECT_MARKER3)) {
|
|
140426
141151
|
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
141152
|
}
|
|
140428
|
-
return
|
|
141153
|
+
return localized.replace(INJECT_MARKER3, `window.__META_DIAGNOSIS_REPORT__ = ${json};`);
|
|
140429
141154
|
}
|
|
140430
141155
|
async function runFacebookAnalysisDiagnosisRender(opts) {
|
|
140431
141156
|
const dataPath = path44.resolve(opts.dataFile);
|
|
@@ -140433,6 +141158,7 @@ async function runFacebookAnalysisDiagnosisRender(opts) {
|
|
|
140433
141158
|
if (opts.snapshotDir?.trim()) {
|
|
140434
141159
|
data = await mergeMetaDiagnosisSnapshotIntoReport(data, path44.resolve(opts.snapshotDir));
|
|
140435
141160
|
}
|
|
141161
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
140436
141162
|
const contentCheck = validateMetaDiagnosisReportContent(data);
|
|
140437
141163
|
if (!contentCheck.ok) {
|
|
140438
141164
|
console.error(`
|
|
@@ -140462,7 +141188,7 @@ async function runFacebookAnalysisDiagnosisRender(opts) {
|
|
|
140462
141188
|
);
|
|
140463
141189
|
const outDir = path44.dirname(outPath);
|
|
140464
141190
|
await fsPromises4.mkdir(outDir, { recursive: true });
|
|
140465
|
-
await fsPromises4.writeFile(outPath, injectReportData4(html, data), "utf8");
|
|
141191
|
+
await fsPromises4.writeFile(outPath, injectReportData4(html, data, lang), "utf8");
|
|
140466
141192
|
const { stats } = contentCheck;
|
|
140467
141193
|
console.log(`
|
|
140468
141194
|
\u2705 Meta\uFF08Facebook\uFF09\u8D26\u6237\u8BCA\u65AD HTML \u62A5\u544A\u5DF2\u751F\u6210\uFF1A${outPath}
|
|
@@ -141152,12 +141878,13 @@ function registerFacebookAnalysisCommands(program2) {
|
|
|
141152
141878
|
"--format <html|xlsx>",
|
|
141153
141879
|
"\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
141880
|
"html"
|
|
141155
|
-
).action(async (opts) => {
|
|
141881
|
+
).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
141882
|
await runFacebookAnalysisRender({
|
|
141157
141883
|
dataFile: opts.data,
|
|
141158
141884
|
snapshotDir: opts.snapshotDir,
|
|
141159
141885
|
out: opts.out,
|
|
141160
|
-
format: opts.format
|
|
141886
|
+
format: opts.format,
|
|
141887
|
+
lang: opts.lang
|
|
141161
141888
|
});
|
|
141162
141889
|
});
|
|
141163
141890
|
root.command("diagnosis-render").description(
|
|
@@ -141165,11 +141892,12 @@ function registerFacebookAnalysisCommands(program2) {
|
|
|
141165
141892
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 meta-account-diagnosis-report.json").option(
|
|
141166
141893
|
"--snapshot-dir <dir>",
|
|
141167
141894
|
"\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) => {
|
|
141895
|
+
).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
141896
|
await runFacebookAnalysisDiagnosisRender({
|
|
141170
141897
|
dataFile: opts.data,
|
|
141171
141898
|
snapshotDir: opts.snapshotDir,
|
|
141172
|
-
out: opts.out
|
|
141899
|
+
out: opts.out,
|
|
141900
|
+
lang: opts.lang
|
|
141173
141901
|
});
|
|
141174
141902
|
});
|
|
141175
141903
|
root.command("account-status").description(
|
|
@@ -142521,6 +143249,8 @@ function formatBingPeriodReportErrors(result) {
|
|
|
142521
143249
|
|
|
142522
143250
|
// src/commands/bing-analysis/render-report.ts
|
|
142523
143251
|
init_report_period();
|
|
143252
|
+
init_lang();
|
|
143253
|
+
init_html();
|
|
142524
143254
|
var TEMPLATE_BASENAME3 = "bing-period-report.html";
|
|
142525
143255
|
var INJECT_MARKER4 = "window.__BING_PERIOD_REPORT__ = window.__BING_PERIOD_REPORT__ || null;";
|
|
142526
143256
|
function resolveSkillTemplatePath6(basename13) {
|
|
@@ -142552,12 +143282,13 @@ function asRecord34(value) {
|
|
|
142552
143282
|
}
|
|
142553
143283
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
142554
143284
|
}
|
|
142555
|
-
function injectReportData5(html, payload) {
|
|
142556
|
-
const
|
|
142557
|
-
|
|
143285
|
+
function injectReportData5(html, payload, lang) {
|
|
143286
|
+
const localized = localizeReportHtml(html, lang);
|
|
143287
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
143288
|
+
if (!localized.includes(INJECT_MARKER4)) {
|
|
142558
143289
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 bing-period-report.html");
|
|
142559
143290
|
}
|
|
142560
|
-
return
|
|
143291
|
+
return localized.replace(INJECT_MARKER4, `window.__BING_PERIOD_REPORT__ = ${json};`);
|
|
142561
143292
|
}
|
|
142562
143293
|
async function runBingAnalysisRender(opts) {
|
|
142563
143294
|
const dataPath = path48.resolve(opts.dataFile);
|
|
@@ -142565,6 +143296,7 @@ async function runBingAnalysisRender(opts) {
|
|
|
142565
143296
|
if (opts.snapshotDir?.trim()) {
|
|
142566
143297
|
data = await mergeBingAnalysisSnapshotIntoReport(data, path48.resolve(opts.snapshotDir));
|
|
142567
143298
|
}
|
|
143299
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
142568
143300
|
const contentCheck = validateBingPeriodReportContent(data);
|
|
142569
143301
|
if (!contentCheck.ok) {
|
|
142570
143302
|
console.error(`
|
|
@@ -142594,7 +143326,7 @@ async function runBingAnalysisRender(opts) {
|
|
|
142594
143326
|
);
|
|
142595
143327
|
const outDir = path48.dirname(outPath);
|
|
142596
143328
|
await fsPromises5.mkdir(outDir, { recursive: true });
|
|
142597
|
-
await fsPromises5.writeFile(outPath, injectReportData5(html, data), "utf8");
|
|
143329
|
+
await fsPromises5.writeFile(outPath, injectReportData5(html, data, lang), "utf8");
|
|
142598
143330
|
const { stats } = contentCheck;
|
|
142599
143331
|
const cover = periodWord(attachPeriodChrome(data).periodChrome.unit, "\u8D26\u6237");
|
|
142600
143332
|
console.log(`
|
|
@@ -142661,11 +143393,12 @@ function registerBingAnalysisCommands(program2) {
|
|
|
142661
143393
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 bing-period-report.json").option(
|
|
142662
143394
|
"--snapshot-dir <dir>",
|
|
142663
143395
|
"\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) => {
|
|
143396
|
+
).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
143397
|
await runBingAnalysisRender({
|
|
142666
143398
|
dataFile: opts.data,
|
|
142667
143399
|
snapshotDir: opts.snapshotDir,
|
|
142668
|
-
out: opts.out
|
|
143400
|
+
out: opts.out,
|
|
143401
|
+
lang: opts.lang
|
|
142669
143402
|
});
|
|
142670
143403
|
});
|
|
142671
143404
|
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 +144153,8 @@ function formatTikTokPeriodReportErrors(result) {
|
|
|
143420
144153
|
|
|
143421
144154
|
// src/commands/tiktok-analysis/render-report.ts
|
|
143422
144155
|
init_report_period();
|
|
144156
|
+
init_lang();
|
|
144157
|
+
init_html();
|
|
143423
144158
|
var TEMPLATE_BASENAME4 = "tiktok-period-report.html";
|
|
143424
144159
|
var INJECT_MARKER5 = "window.__TIKTOK_PERIOD_REPORT__ = window.__TIKTOK_PERIOD_REPORT__ || null;";
|
|
143425
144160
|
function resolveSkillTemplatePath7(basename13) {
|
|
@@ -143451,12 +144186,13 @@ function asRecord37(value) {
|
|
|
143451
144186
|
}
|
|
143452
144187
|
throw new Error("\u62A5\u544A\u6570\u636E\u987B\u4E3A JSON \u5BF9\u8C61");
|
|
143453
144188
|
}
|
|
143454
|
-
function injectReportData6(html, payload) {
|
|
143455
|
-
const
|
|
143456
|
-
|
|
144189
|
+
function injectReportData6(html, payload, lang) {
|
|
144190
|
+
const localized = localizeReportHtml(html, lang);
|
|
144191
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
144192
|
+
if (!localized.includes(INJECT_MARKER5)) {
|
|
143457
144193
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 tiktok-period-report.html");
|
|
143458
144194
|
}
|
|
143459
|
-
return
|
|
144195
|
+
return localized.replace(INJECT_MARKER5, `window.__TIKTOK_PERIOD_REPORT__ = ${json};`);
|
|
143460
144196
|
}
|
|
143461
144197
|
async function runTikTokAnalysisRender(opts) {
|
|
143462
144198
|
const dataPath = path51.resolve(opts.dataFile);
|
|
@@ -143464,6 +144200,7 @@ async function runTikTokAnalysisRender(opts) {
|
|
|
143464
144200
|
if (opts.snapshotDir?.trim()) {
|
|
143465
144201
|
data = await mergeTikTokAnalysisSnapshotIntoReport(data, path51.resolve(opts.snapshotDir));
|
|
143466
144202
|
}
|
|
144203
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
143467
144204
|
const contentCheck = validateTikTokPeriodReportContent(data);
|
|
143468
144205
|
if (!contentCheck.ok) {
|
|
143469
144206
|
console.error(`
|
|
@@ -143493,7 +144230,7 @@ async function runTikTokAnalysisRender(opts) {
|
|
|
143493
144230
|
);
|
|
143494
144231
|
const outDir = path51.dirname(outPath);
|
|
143495
144232
|
await fsPromises6.mkdir(outDir, { recursive: true });
|
|
143496
|
-
await fsPromises6.writeFile(outPath, injectReportData6(html, data), "utf8");
|
|
144233
|
+
await fsPromises6.writeFile(outPath, injectReportData6(html, data, lang), "utf8");
|
|
143497
144234
|
const { stats } = contentCheck;
|
|
143498
144235
|
const cover = periodWord(attachPeriodChrome(data).periodChrome.unit, "\u8D26\u6237");
|
|
143499
144236
|
console.log(`
|
|
@@ -144239,11 +144976,12 @@ function registerTikTokAnalysisCommands(program2) {
|
|
|
144239
144976
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 tiktok-period-report.json").option(
|
|
144240
144977
|
"--snapshot-dir <dir>",
|
|
144241
144978
|
"\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) => {
|
|
144979
|
+
).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
144980
|
await runTikTokAnalysisRender({
|
|
144244
144981
|
dataFile: opts.data,
|
|
144245
144982
|
snapshotDir: opts.snapshotDir,
|
|
144246
|
-
out: opts.out
|
|
144983
|
+
out: opts.out,
|
|
144984
|
+
lang: opts.lang
|
|
144247
144985
|
});
|
|
144248
144986
|
});
|
|
144249
144987
|
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 +145934,8 @@ function formatYandexPeriodReportErrors(result) {
|
|
|
145196
145934
|
|
|
145197
145935
|
// src/commands/yandex-analysis/render-report.ts
|
|
145198
145936
|
init_report_period();
|
|
145937
|
+
init_lang();
|
|
145938
|
+
init_html();
|
|
145199
145939
|
var TEMPLATE_BASENAME5 = "yandex-period-report.html";
|
|
145200
145940
|
var INJECT_MARKER6 = "window.__YANDEX_PERIOD_REPORT__ = window.__YANDEX_PERIOD_REPORT__ || null;";
|
|
145201
145941
|
function resolveSkillTemplatePath8(basename13) {
|
|
@@ -145240,12 +145980,13 @@ function refreshWeeklyFromDaily(data) {
|
|
|
145240
145980
|
}
|
|
145241
145981
|
};
|
|
145242
145982
|
}
|
|
145243
|
-
function injectReportData7(html, payload) {
|
|
145244
|
-
const
|
|
145245
|
-
|
|
145983
|
+
function injectReportData7(html, payload, lang) {
|
|
145984
|
+
const localized = localizeReportHtml(html, lang);
|
|
145985
|
+
const json = JSON.stringify(attachPeriodChrome(stampMetaLang(payload, lang), lang)).replace(/</g, "\\u003c");
|
|
145986
|
+
if (!localized.includes(INJECT_MARKER6)) {
|
|
145246
145987
|
throw new Error("\u62A5\u544A\u6A21\u677F\u7F3A\u5C11\u6570\u636E\u6CE8\u5165\u951A\u70B9\uFF0C\u8BF7\u66F4\u65B0 yandex-period-report.html");
|
|
145247
145988
|
}
|
|
145248
|
-
return
|
|
145989
|
+
return localized.replace(INJECT_MARKER6, `window.__YANDEX_PERIOD_REPORT__ = ${json};`);
|
|
145249
145990
|
}
|
|
145250
145991
|
async function runYandexAnalysisRender(opts) {
|
|
145251
145992
|
const dataPath = path54.resolve(opts.dataFile);
|
|
@@ -145254,6 +145995,7 @@ async function runYandexAnalysisRender(opts) {
|
|
|
145254
145995
|
data = await mergeYandexAnalysisSnapshotIntoReport(data, path54.resolve(opts.snapshotDir));
|
|
145255
145996
|
}
|
|
145256
145997
|
data = refreshWeeklyFromDaily(data);
|
|
145998
|
+
const lang = readReportLangOrExit({ flag: opts.lang, meta: data.meta });
|
|
145257
145999
|
const contentCheck = validateYandexPeriodReportContent(data);
|
|
145258
146000
|
if (!contentCheck.ok) {
|
|
145259
146001
|
console.error(`
|
|
@@ -145281,7 +146023,7 @@ async function runYandexAnalysisRender(opts) {
|
|
|
145281
146023
|
);
|
|
145282
146024
|
const outDir = path54.dirname(outPath);
|
|
145283
146025
|
await fsPromises7.mkdir(outDir, { recursive: true });
|
|
145284
|
-
await fsPromises7.writeFile(outPath, injectReportData7(html, data), "utf8");
|
|
146026
|
+
await fsPromises7.writeFile(outPath, injectReportData7(html, data, lang), "utf8");
|
|
145285
146027
|
const { stats } = contentCheck;
|
|
145286
146028
|
const cover = periodWord(attachPeriodChrome(data).periodChrome.unit, "\u8D26\u6237");
|
|
145287
146029
|
console.log(`
|
|
@@ -145793,11 +146535,12 @@ function registerYandexAnalysisCommands(program2) {
|
|
|
145793
146535
|
).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 yandex-period-report.json").option(
|
|
145794
146536
|
"--snapshot-dir <dir>",
|
|
145795
146537
|
"\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) => {
|
|
146538
|
+
).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
146539
|
await runYandexAnalysisRender({
|
|
145798
146540
|
dataFile: opts.data,
|
|
145799
146541
|
snapshotDir: opts.snapshotDir,
|
|
145800
|
-
out: opts.out
|
|
146542
|
+
out: opts.out,
|
|
146543
|
+
lang: opts.lang
|
|
145801
146544
|
});
|
|
145802
146545
|
});
|
|
145803
146546
|
root.command("account-status").description(
|