siluzan-tso-cli 1.1.48-beta.7 → 1.1.48-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +81 -45
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/assets/meta-period-report-rules.md +1 -1
- package/dist/skill/references/report-templates/README.md +1 -1
- package/dist/skill/references/report-templates/meta-period-report-excel.md +17 -3
- package/dist/skill/references/report-templates/meta-period-report.md +1 -1
- package/dist/skill/report-templates/README.md +1 -1
- package/dist/skill/report-templates/meta-period-report-excel.md +17 -3
- package/dist/skill/report-templates/meta-period-report.md +1 -1
- package/dist/skill/scripts/install.ps1 +1 -1
- package/dist/skill/scripts/install.sh +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
51
51
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
> **注意**:当前为测试版(1.1.48-beta.
|
|
54
|
+
> **注意**:当前为测试版(1.1.48-beta.8),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -133378,6 +133378,28 @@ function genderLabel(gender) {
|
|
|
133378
133378
|
if (g === "female") return "female";
|
|
133379
133379
|
return str(gender) || "unknown";
|
|
133380
133380
|
}
|
|
133381
|
+
function displayResultType(raw) {
|
|
133382
|
+
const v = str(raw);
|
|
133383
|
+
if (!v) return "";
|
|
133384
|
+
const key = v.toLowerCase().replace(/[\s_]+/g, "");
|
|
133385
|
+
if (key === "lead" || key === "leads" || key.includes("leadgrouped") || key.includes("instantform") || key === "onsiteconversionleadgrouped") {
|
|
133386
|
+
return "\u6F5C\u5728\u5BA2\u6237\u4FE1\u606F\uFF08\u8868\u5355\uFF09\u91CF";
|
|
133387
|
+
}
|
|
133388
|
+
return v;
|
|
133389
|
+
}
|
|
133390
|
+
function displayAttribution(raw) {
|
|
133391
|
+
const v = str(raw);
|
|
133392
|
+
if (!v) return "";
|
|
133393
|
+
const key = v.toLowerCase().replace(/[\s_\-/]/g, "");
|
|
133394
|
+
if (key === "multiple" || key === "7dclick" || key === "7dclick1dview" || key.includes("7dclick") || key.includes("7dayclick")) {
|
|
133395
|
+
return "\u70B9\u51FB\u540E 7 \u5929\u5185\u6216\u6D4F\u89C8\u540E 1 \u5929\u5185";
|
|
133396
|
+
}
|
|
133397
|
+
return v;
|
|
133398
|
+
}
|
|
133399
|
+
function hasResults(row) {
|
|
133400
|
+
const n = num3(row.results);
|
|
133401
|
+
return n != null && n > 0;
|
|
133402
|
+
}
|
|
133381
133403
|
|
|
133382
133404
|
// src/commands/facebook-analysis/merge-snapshot.ts
|
|
133383
133405
|
async function readManifest2(snapshotDir) {
|
|
@@ -133619,88 +133641,102 @@ function metricHeaders(currency, firstCol) {
|
|
|
133619
133641
|
"\u5355\u6B21\u6210\u6548\u8D39\u7528"
|
|
133620
133642
|
];
|
|
133621
133643
|
}
|
|
133644
|
+
function moneyText(value) {
|
|
133645
|
+
const n = num3(value);
|
|
133646
|
+
if (n == null) return "\u2014";
|
|
133647
|
+
return `$${n.toFixed(2)}`;
|
|
133648
|
+
}
|
|
133622
133649
|
function metricCells(row) {
|
|
133650
|
+
const results = num3(row.results);
|
|
133651
|
+
const showResults = hasResults({ results });
|
|
133623
133652
|
return [
|
|
133624
133653
|
num3(row.reach) ?? "",
|
|
133625
133654
|
num3(row.impressions) ?? "",
|
|
133626
133655
|
num3(row.frequency) ?? "",
|
|
133627
|
-
|
|
133628
|
-
|
|
133629
|
-
|
|
133656
|
+
displayAttribution(row.attributionSetting),
|
|
133657
|
+
showResults ? displayResultType(row.resultType) : "",
|
|
133658
|
+
showResults ? results ?? "" : "",
|
|
133630
133659
|
num3(row.spend) ?? "",
|
|
133631
|
-
num3(row.costPerResult) ?? ""
|
|
133660
|
+
showResults ? num3(row.costPerResult) ?? "" : ""
|
|
133632
133661
|
];
|
|
133633
133662
|
}
|
|
133634
133663
|
function bullets(value) {
|
|
133635
133664
|
return asArray2(value).map((item) => typeof item === "string" ? item.trim() : "").filter(Boolean);
|
|
133636
133665
|
}
|
|
133637
|
-
function
|
|
133638
|
-
|
|
133666
|
+
function insightLines(section) {
|
|
133667
|
+
const rec = asRecord15(section);
|
|
133668
|
+
const insight = asRecord15(rec?.insight) ?? rec;
|
|
133669
|
+
return [...bullets(insight?.analysis), ...bullets(insight?.advice)];
|
|
133670
|
+
}
|
|
133671
|
+
function numberedSection(index, title, lines) {
|
|
133672
|
+
const body = lines.length > 0 ? lines.join("\n") : "\u672C\u671F\u8BE5\u7EF4\u5EA6\u65E0\u8865\u5145\u8BF4\u660E\u3002";
|
|
133673
|
+
return `${index}. ${title}
|
|
133674
|
+
${body}`;
|
|
133639
133675
|
}
|
|
133640
133676
|
function buildSummaryNarrative(data) {
|
|
133641
|
-
const blocks = [];
|
|
133642
133677
|
const kpis = asRecord15(data.kpis) ?? {};
|
|
133643
133678
|
const meta = asRecord15(data.meta) ?? {};
|
|
133644
|
-
const
|
|
133679
|
+
const sections = asRecord15(data.sections) ?? {};
|
|
133680
|
+
const period = str(meta.periodLabel) || `${str(meta.startDate)} ~ ${str(meta.endDate)}`.trim();
|
|
133681
|
+
const account = str(meta.accountName) || "Facebook \u5E7F\u544A\u8D26\u6237";
|
|
133645
133682
|
const campaign = str(meta.campaignName);
|
|
133646
|
-
|
|
133647
|
-
|
|
133648
|
-
|
|
133649
|
-
|
|
133650
|
-
|
|
133651
|
-
|
|
133652
|
-
|
|
133683
|
+
const resultLabel = displayResultType(kpis.resultType ?? meta.resultType) || "\u6210\u6548";
|
|
133684
|
+
const resultNoun = /潜在客户|lead/i.test(resultLabel) ? "\u4E2A\u6F5C\u5728\u5BA2\u6237\u8868\u5355" : `\u4E2A${resultLabel}`;
|
|
133685
|
+
const firstQuestion = asRecord15(asArray2(data.fourQuestions)[0]);
|
|
133686
|
+
const extra = str(firstQuestion?.verdict);
|
|
133687
|
+
const spendLine = [
|
|
133688
|
+
campaign ? `\uFF08\u5E7F\u544A\u7CFB\u5217\uFF1A${campaign}\uFF09` : "",
|
|
133689
|
+
`\u5171\u6D88\u8017 ${moneyText(kpis.spend)}\uFF0C\u83B7\u53D6 ${num3(kpis.results) ?? "\u2014"} ${resultNoun}\uFF0C\u5E73\u5747\u5355\u6B21\u83B7\u5BA2\u6210\u672C ${moneyText(kpis.costPerResult)}\u3002`,
|
|
133690
|
+
extra
|
|
133691
|
+
].filter(Boolean).join("");
|
|
133692
|
+
const partOne = [`\u4E00\u3001${account}${period ? ` ${period}` : ""} Facebook \u5E7F\u544A\u8D26\u6237`, spendLine].join(
|
|
133693
|
+
"\n"
|
|
133653
133694
|
);
|
|
133654
|
-
|
|
133655
|
-
|
|
133656
|
-
|
|
133657
|
-
|
|
133658
|
-
|
|
133659
|
-
|
|
133660
|
-
|
|
133661
|
-
|
|
133662
|
-
|
|
133663
|
-
|
|
133664
|
-
for (const raw of asArray2(data.recommendations)) {
|
|
133695
|
+
const partTwo = [
|
|
133696
|
+
"\u4E8C\u3001\u5206\u6790\u4E0E\u4F18\u5316\u5EFA\u8BAE",
|
|
133697
|
+
"",
|
|
133698
|
+
numberedSection(1, "\u56FD\u5BB6/\u5730\u533A\u8868\u73B0\u5206\u6790", insightLines(sections.country)),
|
|
133699
|
+
"",
|
|
133700
|
+
numberedSection(2, "\u53D7\u4F17\u7ED3\u6784\u4E0E\u7EBF\u7D22\u8D28\u91CF\u98CE\u9669", insightLines(sections.audience)),
|
|
133701
|
+
"",
|
|
133702
|
+
numberedSection(3, "\u5E7F\u544A\u9891\u6B21\u4E0E\u65E5\u8D8B\u52BF", insightLines(sections.daily))
|
|
133703
|
+
].join("\n");
|
|
133704
|
+
const recBlocks = asArray2(data.recommendations).map((raw, i) => {
|
|
133665
133705
|
const rec = asRecord15(raw);
|
|
133666
|
-
if (!rec)
|
|
133706
|
+
if (!rec) return "";
|
|
133667
133707
|
const title = [str(rec.title), str(rec.tag)].filter(Boolean).join(" \xB7 ");
|
|
133668
|
-
|
|
133669
|
-
}
|
|
133670
|
-
const
|
|
133671
|
-
|
|
133672
|
-
|
|
133673
|
-
|
|
133674
|
-
const analysis = bullets(insight.analysis);
|
|
133675
|
-
const advice = bullets(insight.advice);
|
|
133676
|
-
if (analysis.length) blocks.push(joinBlock(`${key} \u5206\u6790`, analysis));
|
|
133677
|
-
if (advice.length) blocks.push(joinBlock(`${key} \u5EFA\u8BAE`, advice));
|
|
133678
|
-
}
|
|
133679
|
-
return blocks;
|
|
133708
|
+
return numberedSection(i + 1, title || "\u4F18\u5316\u5EFA\u8BAE", bullets(rec.items));
|
|
133709
|
+
}).filter(Boolean);
|
|
133710
|
+
const partThree = ["\u4E09\u3001\u4E0B\u4E00\u6B65\u4F18\u5316\u5EFA\u8BAE", "", recBlocks.join("\n\n") || "\u672C\u671F\u6682\u65E0\u4F18\u5316\u5EFA\u8BAE\u3002"].join(
|
|
133711
|
+
"\n"
|
|
133712
|
+
);
|
|
133713
|
+
return [partOne, partTwo, partThree];
|
|
133680
133714
|
}
|
|
133681
133715
|
function buildMetaPeriodExcelSheets(data) {
|
|
133682
133716
|
const meta = asRecord15(data.meta) ?? {};
|
|
133683
133717
|
const kpis = asRecord15(data.kpis) ?? {};
|
|
133684
133718
|
const tables = asRecord15(data.tables) ?? {};
|
|
133685
133719
|
const currency = str(meta.currency) || "USD";
|
|
133720
|
+
const resultType = displayResultType(kpis.resultType ?? meta.resultType);
|
|
133721
|
+
const attribution = displayAttribution(kpis.attributionSetting ?? meta.attributionSetting);
|
|
133686
133722
|
const summaryRows = [
|
|
133687
133723
|
metricHeaders(currency, "\u76EE\u6807"),
|
|
133688
133724
|
[
|
|
133689
|
-
|
|
133725
|
+
resultType,
|
|
133690
133726
|
...metricCells({
|
|
133691
133727
|
...kpis,
|
|
133692
|
-
attributionSetting:
|
|
133693
|
-
resultType
|
|
133728
|
+
attributionSetting: attribution,
|
|
133729
|
+
resultType
|
|
133694
133730
|
})
|
|
133695
133731
|
],
|
|
133696
133732
|
[],
|
|
133697
133733
|
...buildSummaryNarrative(data).map((text2) => [text2])
|
|
133698
133734
|
];
|
|
133699
|
-
const dailyRows = [metricHeaders(currency, "\u65E5
|
|
133735
|
+
const dailyRows = [metricHeaders(currency, "\u5355\u65E5")];
|
|
133700
133736
|
for (const raw of asArray2(tables.daily)) {
|
|
133701
133737
|
const row = asRecord15(raw);
|
|
133702
133738
|
if (!row) continue;
|
|
133703
|
-
dailyRows.push([
|
|
133739
|
+
dailyRows.push([normalizeInsightDate(row.date), ...metricCells(row)]);
|
|
133704
133740
|
}
|
|
133705
133741
|
const countryRows = [metricHeaders(currency, "\u56FD\u5BB6/\u5730\u533A")];
|
|
133706
133742
|
for (const raw of asArray2(tables.countries)) {
|
|
@@ -133734,7 +133770,7 @@ function buildMetaPeriodExcelSheets(data) {
|
|
|
133734
133770
|
audienceRows.push([str(row.age), str(row.gender), ...metricCells(row)]);
|
|
133735
133771
|
}
|
|
133736
133772
|
return [
|
|
133737
|
-
{ name: "\u6C47\u603B", rows: summaryRows },
|
|
133773
|
+
{ name: "\u6C47\u603B\u6570\u636E", rows: summaryRows },
|
|
133738
133774
|
{ name: "\u65E5\u8D8B\u52BF", rows: dailyRows },
|
|
133739
133775
|
{ name: "\u56FD\u5BB6", rows: countryRows },
|
|
133740
133776
|
{ name: "\u5E7F\u544A\u7CFB\u5217", rows: campaignRows2 },
|
package/dist/skill/_meta.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
| `google-account-diagnosis-report.md` | Google 账户深度诊断(健康度/转化/结构等) |
|
|
28
28
|
| `google-ads-diagnosis.md` | Google **广告诊断**完整纲要(HTML 区块、**每日趋势 2 位小数**、**每模块必填分析/建议**) |
|
|
29
29
|
| `meta-period-report.md` / `.html` | **Meta(Facebook)周期报告(默认)**:四步流程 → `facebook-analysis render` 出 HTML,见 P4-FB |
|
|
30
|
-
| `meta-period-report-excel.md` | **仅用户要 Excel 时**:5 Sheet
|
|
30
|
+
| `meta-period-report-excel.md` | **仅用户要 Excel 时**:5 Sheet(**汇总数据**/日趋势/国家/广告系列/受众,汇总 KPI 下是一/二/三);`facebook-analysis render --format xlsx` |
|
|
31
31
|
| `meta-account-diagnosis-report.md` / `.html` | **Meta(Facebook)诊断报告(默认)**:四步流程 → `facebook-analysis diagnosis-render` 出 HTML(在 7 Section 内对齐 Google 诊断结构,未覆盖小节标 `notAvailable`) |
|
|
32
32
|
| `tiktok-period-report.md` / `.html` | **TikTok 广告主周期报告(默认)**:四步流程 → `tiktok-analysis render` 出 HTML |
|
|
33
33
|
| `bing-period-report.md` / `.html` | **Bing(BingV2)分析报告(默认)**:四步流程 → `bing-analysis render` 出 HTML |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **适用场景**:用户**明确要求 Excel / xlsx / 表格形式**时读本文件。
|
|
4
4
|
> 用户未指定格式时,**默认交付 HTML**,走 `meta-period-report.md` 标准四步。
|
|
5
5
|
|
|
6
|
-
> 对照业务交付物:`光盈光电7月fb广告报告.xlsx`(5 个 Sheet
|
|
6
|
+
> 对照业务交付物:`光盈光电7月fb广告报告.xlsx`(5 个 Sheet:**汇总数据** / 日趋势 / 国家 / 广告系列 / 受众)。
|
|
7
7
|
> **由 CLI 生成**:`facebook-analysis render --format xlsx`,不要手写 xlsx,也不要假设还有别的 excel 子命令。
|
|
8
8
|
> **ID 列硬规则**:账户 / 系列等 id **一律写成字符串(文本)**;见 `references/core/agent-conventions.md`。
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
| Sheet | 中文名 | CLI `--sections` | 落盘文件 | 角色 |
|
|
15
15
|
| ----- | ---------- | ---------------- | ---------------------- | ---------------------------- |
|
|
16
|
-
| 1 |
|
|
16
|
+
| 1 | **汇总数据** | `overview` | `overview-<id>.json` | KPI 首行 + **一 / 二 / 三** 叙事 |
|
|
17
17
|
| 2 | **日趋势** | `daily` | `daily-<id>.json` | 按日表(`days[]`) |
|
|
18
18
|
| 3 | **国家** | `country` | `country-<id>.json` | 国家/地区表 |
|
|
19
19
|
| 4 | **广告系列** | `campaigns` | `campaigns-<id>.json` | 系列表 |
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
| 已花费金额 (USD) | `spend` | 账户币种,非 micros |
|
|
37
37
|
| 单次成效费用 | `costPerResult` | CPL |
|
|
38
38
|
|
|
39
|
-
Sheet 2
|
|
39
|
+
Sheet 2 首列:`单日`(`date`,YYYY-MM-DD)。
|
|
40
40
|
Sheet 3 首列:`国家/地区`(`countryOrRegion`)。
|
|
41
41
|
Sheet 4 首列:`广告系列名称`(`campaignName`)。
|
|
42
42
|
Sheet 5 另加:`年龄`(`age`)、`性别`(`gender`)。
|
|
@@ -45,6 +45,20 @@ Sheet 5 另加:`年龄`(`age`)、`性别`(`gender`)。
|
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
+
## 汇总数据叙事(KPI 下方,格式的一部分)
|
|
49
|
+
|
|
50
|
+
空 1~2 行后,**只写三块**,标题字面必须是:
|
|
51
|
+
|
|
52
|
+
| 块 | 标题 | 内容从哪来 |
|
|
53
|
+
| -- | ---- | ---------- |
|
|
54
|
+
| **一** | `一、{账户名} {周期} Facebook 广告账户` | 系列名 + 花费/成效/单次成本(CLI 用 KPI 拼);可接 `fourQuestions[0].verdict` |
|
|
55
|
+
| **二** | `二、分析与优化建议` | 下面固定 3 小节:`1. 国家/地区表现分析`、`2. 受众结构与线索质量风险`、`3. 广告频次与日趋势`(来自 `sections.country/audience/daily.insight`) |
|
|
56
|
+
| **三** | `三、下一步优化建议` | `recommendations[]` 按 `1. 2. 3.` 编号 |
|
|
57
|
+
|
|
58
|
+
**禁止**在 Excel 汇总数据里写「钱花得值不值?」四问标题,或 `daily 分析` / `country 建议` 这种机读标题。四问仍写在 Agent JSON 里给 HTML 用。
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
48
62
|
## 拉数与渲染
|
|
49
63
|
|
|
50
64
|
```bash
|
|
@@ -51,7 +51,7 @@ siluzan-tso facebook-analysis render \
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
同时要 HTML + Excel:`--format html,xlsx`。
|
|
54
|
-
版式见 **`report-templates/meta-period-report-excel.md`**(5 Sheet
|
|
54
|
+
版式见 **`report-templates/meta-period-report-excel.md`**(5 Sheet:**汇总数据** / 日趋势 / 国家 / 广告系列 / 受众;汇总 KPI 下是 **一 / 二 / 三**)。
|
|
55
55
|
|
|
56
56
|
---
|
|
57
57
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
| `google-account-diagnosis-report.md` | Google 账户深度诊断(健康度/转化/结构等) |
|
|
28
28
|
| `google-ads-diagnosis.md` | Google **广告诊断**完整纲要(HTML 区块、**每日趋势 2 位小数**、**每模块必填分析/建议**) |
|
|
29
29
|
| `meta-period-report.md` / `.html` | **Meta(Facebook)周期报告(默认)**:四步流程 → `facebook-analysis render` 出 HTML,见 P4-FB |
|
|
30
|
-
| `meta-period-report-excel.md` | **仅用户要 Excel 时**:5 Sheet
|
|
30
|
+
| `meta-period-report-excel.md` | **仅用户要 Excel 时**:5 Sheet(**汇总数据**/日趋势/国家/广告系列/受众,汇总 KPI 下是一/二/三);`facebook-analysis render --format xlsx` |
|
|
31
31
|
| `meta-account-diagnosis-report.md` / `.html` | **Meta(Facebook)诊断报告(默认)**:四步流程 → `facebook-analysis diagnosis-render` 出 HTML(在 7 Section 内对齐 Google 诊断结构,未覆盖小节标 `notAvailable`) |
|
|
32
32
|
| `tiktok-period-report.md` / `.html` | **TikTok 广告主周期报告(默认)**:四步流程 → `tiktok-analysis render` 出 HTML |
|
|
33
33
|
| `bing-period-report.md` / `.html` | **Bing(BingV2)分析报告(默认)**:四步流程 → `bing-analysis render` 出 HTML |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **适用场景**:用户**明确要求 Excel / xlsx / 表格形式**时读本文件。
|
|
4
4
|
> 用户未指定格式时,**默认交付 HTML**,走 `meta-period-report.md` 标准四步。
|
|
5
5
|
|
|
6
|
-
> 对照业务交付物:`光盈光电7月fb广告报告.xlsx`(5 个 Sheet
|
|
6
|
+
> 对照业务交付物:`光盈光电7月fb广告报告.xlsx`(5 个 Sheet:**汇总数据** / 日趋势 / 国家 / 广告系列 / 受众)。
|
|
7
7
|
> **由 CLI 生成**:`facebook-analysis render --format xlsx`,不要手写 xlsx,也不要假设还有别的 excel 子命令。
|
|
8
8
|
> **ID 列硬规则**:账户 / 系列等 id **一律写成字符串(文本)**;见 `references/core/agent-conventions.md`。
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
| Sheet | 中文名 | CLI `--sections` | 落盘文件 | 角色 |
|
|
15
15
|
| ----- | ---------- | ---------------- | ---------------------- | ---------------------------- |
|
|
16
|
-
| 1 |
|
|
16
|
+
| 1 | **汇总数据** | `overview` | `overview-<id>.json` | KPI 首行 + **一 / 二 / 三** 叙事 |
|
|
17
17
|
| 2 | **日趋势** | `daily` | `daily-<id>.json` | 按日表(`days[]`) |
|
|
18
18
|
| 3 | **国家** | `country` | `country-<id>.json` | 国家/地区表 |
|
|
19
19
|
| 4 | **广告系列** | `campaigns` | `campaigns-<id>.json` | 系列表 |
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
| 已花费金额 (USD) | `spend` | 账户币种,非 micros |
|
|
37
37
|
| 单次成效费用 | `costPerResult` | CPL |
|
|
38
38
|
|
|
39
|
-
Sheet 2
|
|
39
|
+
Sheet 2 首列:`单日`(`date`,YYYY-MM-DD)。
|
|
40
40
|
Sheet 3 首列:`国家/地区`(`countryOrRegion`)。
|
|
41
41
|
Sheet 4 首列:`广告系列名称`(`campaignName`)。
|
|
42
42
|
Sheet 5 另加:`年龄`(`age`)、`性别`(`gender`)。
|
|
@@ -45,6 +45,20 @@ Sheet 5 另加:`年龄`(`age`)、`性别`(`gender`)。
|
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
+
## 汇总数据叙事(KPI 下方,格式的一部分)
|
|
49
|
+
|
|
50
|
+
空 1~2 行后,**只写三块**,标题字面必须是:
|
|
51
|
+
|
|
52
|
+
| 块 | 标题 | 内容从哪来 |
|
|
53
|
+
| -- | ---- | ---------- |
|
|
54
|
+
| **一** | `一、{账户名} {周期} Facebook 广告账户` | 系列名 + 花费/成效/单次成本(CLI 用 KPI 拼);可接 `fourQuestions[0].verdict` |
|
|
55
|
+
| **二** | `二、分析与优化建议` | 下面固定 3 小节:`1. 国家/地区表现分析`、`2. 受众结构与线索质量风险`、`3. 广告频次与日趋势`(来自 `sections.country/audience/daily.insight`) |
|
|
56
|
+
| **三** | `三、下一步优化建议` | `recommendations[]` 按 `1. 2. 3.` 编号 |
|
|
57
|
+
|
|
58
|
+
**禁止**在 Excel 汇总数据里写「钱花得值不值?」四问标题,或 `daily 分析` / `country 建议` 这种机读标题。四问仍写在 Agent JSON 里给 HTML 用。
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
48
62
|
## 拉数与渲染
|
|
49
63
|
|
|
50
64
|
```bash
|
|
@@ -51,7 +51,7 @@ siluzan-tso facebook-analysis render \
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
同时要 HTML + Excel:`--format html,xlsx`。
|
|
54
|
-
版式见 **`report-templates/meta-period-report-excel.md`**(5 Sheet
|
|
54
|
+
版式见 **`report-templates/meta-period-report-excel.md`**(5 Sheet:**汇总数据** / 日趋势 / 国家 / 广告系列 / 受众;汇总 KPI 下是 **一 / 二 / 三**)。
|
|
55
55
|
|
|
56
56
|
---
|
|
57
57
|
|
|
@@ -9,7 +9,7 @@ $ErrorActionPreference = 'Stop'
|
|
|
9
9
|
# -- Package info (injected at build time) ------------------------------------
|
|
10
10
|
$PKG_NAME = 'siluzan-tso-cli'
|
|
11
11
|
# PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
|
|
12
|
-
$PKG_VERSION = '1.1.48-beta.
|
|
12
|
+
$PKG_VERSION = '1.1.48-beta.8'
|
|
13
13
|
$CLI_BIN = 'siluzan-tso'
|
|
14
14
|
$SKILL_LABEL = 'Siluzan TSO'
|
|
15
15
|
$INSTALL_CMD = 'npm install -g siluzan-tso-cli@beta'
|
|
@@ -9,7 +9,7 @@ set -euo pipefail
|
|
|
9
9
|
# -- Package info (injected at build time) ------------------------------------
|
|
10
10
|
readonly PKG_NAME="siluzan-tso-cli"
|
|
11
11
|
# PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
|
|
12
|
-
readonly PKG_VERSION="1.1.48-beta.
|
|
12
|
+
readonly PKG_VERSION="1.1.48-beta.8"
|
|
13
13
|
readonly CLI_BIN="siluzan-tso"
|
|
14
14
|
readonly SKILL_LABEL="Siluzan TSO"
|
|
15
15
|
readonly INSTALL_CMD="npm install -g siluzan-tso-cli@beta"
|