@guandata/guancli 1.0.31 → 1.0.32

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.
@@ -0,0 +1,146 @@
1
+ # 复合指标创建与编辑
2
+
3
+ 复合指标用于通过公式组合已有指标,例如“客单价 = 销售额 / 订单数”。
4
+
5
+ ## 触发场景
6
+
7
+ - 用户说“创建复合指标”“基于多个指标算一个指标”。
8
+ - 用户描述的口径是已有指标之间的四则运算。
9
+ - 用户要编辑一个 `subType=COMPOSITE` 的指标。
10
+
11
+ ## 创建必填信息
12
+
13
+ | 字段 | 中文 | 说明 |
14
+ | --- | --- | --- |
15
+ | `projectId` | 主题 ID | 指标所属主题 |
16
+ | `subType` | 指标类型 | 固定 `COMPOSITE` |
17
+ | `name` | 指标名称 | 最长 50 |
18
+ | `formula` | 计算公式 | 使用已有指标 ID,形如 `[metric_sales] / [metric_orders]` |
19
+ | `useExpressionMetricCommonDims` | 是否沿用公式指标共有维度 | Web 默认 `true` |
20
+ | `applicableDims` | 适用维度 | 引用指标的共有维度字段 ID 数组;手动选择时不能为空 |
21
+ | `desc` | 业务口径 | 最长 1000 |
22
+ | `parentDirId` | 保存至/所属文件夹 | 创建时需要 |
23
+ | `businessOwner` | 责任人 | 创建时需要 |
24
+ | `publish` | 保存方式 | `true` 上线,`false` 草稿 |
25
+
26
+ 专属可选字段:
27
+
28
+ | 字段 | 中文 | 说明 |
29
+ | --- | --- | --- |
30
+ | `timeDim` | 时间维度 | 最终适用维度中存在时间字段时选择一个 |
31
+
32
+ 通用可选字段见 `metric-common-fields.md`。
33
+
34
+ ## 公式与引用指标
35
+
36
+ 复合指标公式在最终 payload 中使用指标 ID,而不是指标中文名:
37
+
38
+ ```text
39
+ [metric_sales_amount] / [metric_order_count]
40
+ ```
41
+
42
+ 处理规则:
43
+
44
+ - 涉及复合指标 `formula` 时,先读取 `metric-expression-rules.md`。
45
+ - 先用 `guancli metric search <关键词> -d <projectId> -f json` 查询公式中的指标,再用 `guancli metric get <metric_id> --brief` 核对名称、类型、状态和适用维度。
46
+ - 公式只能引用数值型指标;不要引用当前正在编辑的指标本身。
47
+ - 公式支持 `+`、`-`、`*`、`/`、括号、数字和 `[指标ID]`;不要主动生成函数、窗口函数或 SQL 片段。
48
+ - 公式中的 `[xxx]` 会被后端解析为上游指标 ID,并参与循环引用校验。
49
+ - 如果用户用中文名描述公式,先转换成 ID 公式,再把“中文公式”和“ID 公式”都展示给用户确认。
50
+
51
+ ## 适用维度
52
+
53
+ 复合指标的适用维度来自公式中引用指标的共有维度:
54
+
55
+ - `useExpressionMetricCommonDims=true`:沿用表达式中指标的共用维度。需要根据引用指标详情整理共有维度;如果没有共有维度,Web 会报“计算公式来源指标无共有适用维度,请检查”。
56
+ - `useExpressionMetricCommonDims=false`:从共有维度中手动选择 `applicableDims`,至少选择一个。
57
+ - 如果最终适用维度中有时间类型字段,需要选择一个 `timeDim`。
58
+ - 不要把某个上游指标独有的维度写进 `applicableDims`。
59
+
60
+ ## 信息收集
61
+
62
+ 如果用户只说“帮我创建一个复合指标”,先收集:
63
+
64
+ 1. 指标主题和保存目录。
65
+ 2. 公式中要引用哪些已有指标;中文名先搜索确认唯一指标。
66
+ 3. 计算公式,转换成 `[metric_id]` 形式。
67
+ 4. 是否沿用共有维度;如果手动选择,确认具体维度和时间维度。
68
+ 5. 数据格式:默认、数值、货币、百分比;如需指定,确认小数位、千分位、货币符号/前后缀、数量级单位、百分比是否除以 100。
69
+ 6. 指标名称、业务口径、是否保存并上线。
70
+ 7. 责任人和必填 `bizAttrs`。
71
+
72
+ ## JSON 模板
73
+
74
+ ```json
75
+ {
76
+ "projectId": "<metric_project_id>",
77
+ "subType": "COMPOSITE",
78
+ "name": "客单价",
79
+ "engName": "avg_order_value",
80
+ "formula": "[<sales_amount_metric_id>] / [<order_count_metric_id>]",
81
+ "useExpressionMetricCommonDims": true,
82
+ "applicableDims": ["<common_dim_fd_id_1>", "<common_dim_fd_id_2>"],
83
+ "timeDim": "<time_dim_fd_id>",
84
+ "format": {
85
+ "formatType": "NUMBER",
86
+ "decimalPlaces": 2,
87
+ "useThousandsSeparator": true,
88
+ "prefixUnit": null,
89
+ "showPrefixUnit": true,
90
+ "prefix": "",
91
+ "suffix": ""
92
+ },
93
+ "desc": "销售金额除以订单数,用于衡量平均每笔订单贡献的销售额。",
94
+ "parentDirId": "<metric_dir_id>",
95
+ "businessOwner": "<user_id>",
96
+ "publish": false
97
+ }
98
+ ```
99
+
100
+ 没有时间维度时删除 `timeDim`;没有英文名称时删除 `engName`;未指定数据格式时删除 `format` 或传 `{}`。如需业务属性,按 `metric-common-fields.md` 补充 `bizAttrs`。
101
+
102
+ ## 创建步骤
103
+
104
+ `guancli metric create` 当前是原子指标专用 endpoint;复合指标创建使用 `guancli fetch`。
105
+
106
+ 1. 生成 `/tmp/composite_metric.json`。
107
+ 2. 本地/人工检查 JSON、公式引用指标、共有适用维度、必填业务属性。
108
+ 3. 按 `metric-common-fields.md` 向用户摘要并确认。
109
+ 4. 用户确认后,不调用原子指标 `save-precheck`;复合指标 Web 创建没有 save-precheck。
110
+ 5. 提交真实创建:
111
+
112
+ ```bash
113
+ guancli fetch POST /api/metric-platform/metrics/composite-metrics --stdin < /tmp/composite_metric.json
114
+ ```
115
+
116
+ 6. 响应返回指标 ID 后回读:
117
+
118
+ ```bash
119
+ guancli metric get <metric_id> --brief
120
+ ```
121
+
122
+ ## 编辑步骤
123
+
124
+ 复合指标没有原子指标的 save-precheck;主要校验公式或筛选变化是否影响下游指标/卡片。
125
+
126
+ 1. 读取当前详情:
127
+
128
+ ```bash
129
+ guancli metric get <metric_id> -f json
130
+ ```
131
+
132
+ 2. 基于当前详情生成完整编辑 payload,例如 `/tmp/composite_metric_update.json`。至少包含 `projectId`、`subType`、`name`、`formula`、`useExpressionMetricCommonDims`、`applicableDims`、`desc`、`publish`。
133
+ 3. 如果修改了 `formula` 或 `filter`,先调用影响校验:
134
+
135
+ ```bash
136
+ guancli fetch POST /api/metric-platform/metrics/composite-metrics/<metric_id>/validate-update-impact --stdin < /tmp/composite_metric_update.json
137
+ ```
138
+
139
+ 4. 如果返回 `hasChanged=true` 且 `affectedMetrics` 或 `affectedCards` 非空,展示受影响指标和卡片,等待用户二次确认。
140
+ 5. 提交真实编辑:
141
+
142
+ ```bash
143
+ guancli fetch POST /api/metric-platform/metrics/composite-metrics/<metric_id> --stdin < /tmp/composite_metric_update.json
144
+ ```
145
+
146
+ 6. 保存后回读确认。
@@ -0,0 +1,70 @@
1
+ # 指标删除
2
+
3
+ 指标删除适用于原子指标、复合指标、衍生指标和快捷引用指标。删除流程是通用的,不需要按指标类型走不同 endpoint。
4
+
5
+ ## Web 同款行为
6
+
7
+ Web 的单指标删除弹窗会先做删除影响校验:
8
+
9
+ ```bash
10
+ guancli fetch GET /api/metric-platform/metrics/<metric_id>/validate-delete-impact
11
+ ```
12
+
13
+ 响应结构与编辑影响校验一致:
14
+
15
+ | 字段 | 中文 | 说明 |
16
+ | --- | --- | --- |
17
+ | `hasChanged` | 是否存在变更影响 | 删除校验通常为 `true` |
18
+ | `affectedMetrics` | 下游指标 | 仍引用该指标的指标列表 |
19
+ | `affectedCards` | 下游指标卡片 | 仍引用该指标的卡片列表 |
20
+
21
+ 如果 `affectedMetrics` 或 `affectedCards` 非空,Web 会提示“指标已被以下资源使用,暂无法删除”,只允许用户查看影响并关闭弹窗,不会提交删除。
22
+
23
+ 只有影响列表为空时,Web 才展示“删除后无法恢复”的确认弹窗;用户确认后调用:
24
+
25
+ ```bash
26
+ guancli fetch POST /api/metric-platform/metrics/<metric_id>/delete
27
+ ```
28
+
29
+ ## CLI 推荐流程
30
+
31
+ 优先使用封装命令:
32
+
33
+ ```bash
34
+ guancli metric delete <metric_id>
35
+ ```
36
+
37
+ 该命令默认只执行删除影响校验并输出结果,不会真实删除。输出 `deletable=true` 时,再向用户确认“删除后无法恢复”。
38
+
39
+ 用户明确确认后执行:
40
+
41
+ ```bash
42
+ guancli metric delete <metric_id> --confirm
43
+ ```
44
+
45
+ `--confirm` 也会先重新执行删除影响校验;如果此时发现下游指标或卡片,仍然阻断删除,不会调用 delete 接口。
46
+
47
+ ## 信息收集
48
+
49
+ 如果用户只说“帮我删除一个指标”,先收集或查询:
50
+
51
+ 1. 指标 ID;如果只给名称,先用 `guancli metric search <关键词> -f json` 查候选。
52
+ 2. 用 `guancli metric get <metric_id> --brief` 核对指标名称、类型、主题、目录和状态。
53
+ 3. 运行 `guancli metric delete <metric_id>` 查看删除影响。
54
+ 4. 如果可删除,向用户确认删除对象和“删除后无法恢复”。
55
+ 5. 用户明确确认后执行 `guancli metric delete <metric_id> --confirm`。
56
+
57
+ ## 影响展示
58
+
59
+ 影响校验返回下游资源时,需要向用户展示:
60
+
61
+ - 下游指标:`id`、`name`、`subType`;若有 `linkMetricId`,说明是快捷引用关联的原始指标。
62
+ - 下游卡片:`id`、`name`。
63
+
64
+ 存在下游资源时不要提供 `--confirm` 继续删除的建议;应提示用户先调整或删除引用关系。
65
+
66
+ ## 常见判断
67
+
68
+ - 删除是不可恢复操作,即使 `publish=false` 的草稿也要明确确认。
69
+ - 不要把“删除影响校验通过”说成已经删除成功。
70
+ - 删除成功后可尝试 `guancli metric get <metric_id> --brief` 或重新搜索确认资源已不可见;如果后端返回已删除/不存在,视为删除完成。
@@ -0,0 +1,384 @@
1
+ # 衍生指标创建与编辑
2
+
3
+ 衍生指标用于在基础指标之上配置同比/环比、最近 N、累计、期末值、业务限定,或通过组合衍生公式引用多个指标。
4
+
5
+ ## 触发场景
6
+
7
+ - 用户说“创建衍生指标”“做同比/环比”“最近 N 天/周/月”“本月累计/年累计”“期末值”“业务限定”。
8
+ - 用户要编辑一个 `subType=DERIVED` 的指标。
9
+
10
+ ## 创建必填信息
11
+
12
+ | 字段 | 中文 | 说明 |
13
+ | --- | --- | --- |
14
+ | `projectId` | 主题 ID | 指标所属主题 |
15
+ | `subType` | 指标类型 | 固定 `DERIVED` |
16
+ | `name` | 指标名称 | 最长 50 |
17
+ | `deriveSetting` | 衍生配置 | 见下方细节 |
18
+ | `desc` | 业务口径 | 最长 1000 |
19
+ | `parentDirId` | 保存至/所属文件夹 | 创建时需要 |
20
+ | `businessOwner` | 责任人 | 创建时需要 |
21
+ | `publish` | 保存方式 | `true` 上线,`false` 草稿 |
22
+
23
+ 普通衍生还需要:
24
+
25
+ | 字段 | 中文 | 说明 |
26
+ | --- | --- | --- |
27
+ | `baseMetricId` | 衍生自/基础指标 ID | 不能是快捷引用指标;先用 `metric search/get` 确认 |
28
+
29
+ 组合衍生不选择单个 `baseMetricId`,核心配置在 `deriveSetting.formula`。
30
+
31
+ 通用可选字段见 `metric-common-fields.md`。`BIZ_CONDITION` 类型必须提供顶层 `filter`。
32
+
33
+ ## 衍生类型
34
+
35
+ | `advType` / `deriveType` | 中文 | 说明 |
36
+ | --- | --- | --- |
37
+ | `COMPARATIVE` | 同比/环比 | 需要基础指标有时间维度;配置本期、对比期和输出值类型 |
38
+ | `RECENT_X` | 最近 N | 只能衍生自原子指标;如最近 7 天、最近 3 月 |
39
+ | `XTD` | 累计计算 | 周/月/季/年至今累计,或近 N 个粒度累计 |
40
+ | `LAST` | 期末值 | 按基础指标时间维度取期末值 |
41
+ | `BIZ_CONDITION` | 业务限定 | 在基础指标上附加业务筛选,顶层 `filter` 必填 |
42
+ | `deriveType=COMPOSITE` | 组合衍生 | 通过 `deriveSetting.formula` 引用多个指标 |
43
+
44
+ ## `deriveSetting` 通用结构
45
+
46
+ | 字段 | 中文 | 说明 |
47
+ | --- | --- | --- |
48
+ | `deriveType` | 衍生大类 | 普通衍生为 `ORDINARY`;组合衍生为 `COMPOSITE` |
49
+ | `advType` | 衍生方式 | 普通衍生必填;组合衍生提交前可删除 |
50
+ | `advValue` | 衍生方式配置 | 普通衍生必填;组合衍生可为 `null` 或不传 |
51
+ | `formula` | 组合衍生公式 | 组合衍生必填,使用 `[metric_id]` 引用指标 |
52
+
53
+ 时间粒度 `granularity` 常用值:
54
+
55
+ | 值 | 中文 |
56
+ | --- | --- |
57
+ | `DAY` | 日 |
58
+ | `WEEK` | 周 |
59
+ | `MONTH` | 月 |
60
+ | `QUARTER` | 季度 |
61
+ | `YEAR` | 年 |
62
+ | `NONE` | 历史数据 |
63
+ | `YEARBYWEEK` | 年同比按周 |
64
+ | `ENDOFMONTH` | 上月末 |
65
+ | `ENDOFQUARTER` | 上季度末 |
66
+ | `ENDOFYEAR` | 上年末 |
67
+
68
+ 基准日期 `baseline` 常用值:
69
+
70
+ | 值 | 中文 |
71
+ | --- | --- |
72
+ | `DATE_RANGE_PARAM_LEFT` | 基于日期筛选:开始日期 |
73
+ | `DATE_RANGE_PARAM_RIGHT` | 基于日期筛选:结束日期 |
74
+
75
+ ## 同比/环比 `COMPARATIVE`
76
+
77
+ 用于描述本期时间范围、上期/对比期时间范围、输出值类型。
78
+
79
+ 字段明细:
80
+
81
+ | 字段 | 中文 | 说明 |
82
+ | --- | --- | --- |
83
+ | `advValue.advType` | 高级计算类型 | 固定 `COMPARATIVE` |
84
+ | `dateFdId` | 日期字段 ID | 来自基础指标时间维度;必填 |
85
+ | `dateFdName` | 日期字段名称 | 建议带上 |
86
+ | `granularity` | 时间粒度 | `DAY/WEEK/MONTH/QUARTER/YEAR` |
87
+ | `window` | 本期时间范围 | Web 默认常见为 `{ "offset": 0 }` |
88
+ | `offsetType` | 对比方式粒度 | 如 `MONTH` 月环比、`YEAR` 年同比、`ENDOFMONTH` 上月末 |
89
+ | `offset` | 偏移量 | 同环比默认 `1`;自定义偏移可大于 1 |
90
+ | `fixedBase` | 固定对比期 | 自定义时间范围时使用 |
91
+ | `valueType` | 数值设置 | `VALUE`、`RATE`、`RAWDATA`、`CUSTOM` |
92
+ | `growthRateType` | 增长率算法 | `RATE` 时必填:`NORMAL` 或 `ABS` |
93
+ | `formulaSetting` | 自定义公式 | `CUSTOM` 时必填,由公式编辑器生成 |
94
+
95
+ `window` 写法:
96
+
97
+ | 形态 | JSON | 说明 |
98
+ | --- | --- | --- |
99
+ | 当前粒度本期 | `{ "offset": 0 }` | 当前日/周/月/季/年 |
100
+ | 上一个粒度区间 | `{ "offset": 1 }` | 上日/上周/上月等 |
101
+ | 相对日期 | `{ "offset": 3 }` | 相对本期前 3 个粒度 |
102
+ | 固定区间 | `{ "withMacro": false, "period": ["2026-05-01", "2026-05-31"] }` | 固定日期范围 |
103
+ | 时间宏 | `{ "withMacro": true, "period": ["{{{}}}", "{{{}}}"] }` | 使用时间宏表达式 |
104
+
105
+ 数值设置:
106
+
107
+ | `valueType` | 中文 | 额外字段 |
108
+ | --- | --- | --- |
109
+ | `VALUE` | 增长值 | 无,含义为本期数据 - 上期数据 |
110
+ | `RATE` | 增长率 | `growthRateType` 必填 |
111
+ | `RAWDATA` | 对比值 | 无,直接输出上期/对比期数据 |
112
+ | `CUSTOM` | 自定义公式 | `formulaSetting` 必填 |
113
+
114
+ 示例:月环比增长率:
115
+
116
+ ```json
117
+ "deriveSetting": {
118
+ "deriveType": "ORDINARY",
119
+ "advType": "COMPARATIVE",
120
+ "advValue": {
121
+ "advType": "COMPARATIVE",
122
+ "dateFdId": "<time_fd_id>",
123
+ "dateFdName": "订单日期",
124
+ "granularity": "MONTH",
125
+ "window": { "offset": 0 },
126
+ "offsetType": "MONTH",
127
+ "offset": 1,
128
+ "valueType": "RATE",
129
+ "growthRateType": "NORMAL"
130
+ }
131
+ }
132
+ ```
133
+
134
+ ## 最近 N `RECENT_X`
135
+
136
+ 只能衍生自原子指标。
137
+
138
+ | 字段 | 中文 | 说明 |
139
+ | --- | --- | --- |
140
+ | `advValue.advType` | 高级计算类型 | 固定 `RECENT_X` |
141
+ | `granularity` | 时间粒度 | `DAY/WEEK/MONTH/QUARTER/YEAR` |
142
+ | `baseline` | 基准日期 | `DATE_RANGE_PARAM_LEFT` 或 `DATE_RANGE_PARAM_RIGHT` |
143
+ | `baselineOffset` | 起止偏移 | 二元数组 `[startOffset, endOffset]` |
144
+ | `baselineOffsetDynamicParameters` | 动态参数偏移 | 如 `[DYNAMIC_PARAMS.N]`,非空时优先于 `baselineOffset` |
145
+ | `aggrType` | 计算方式 | 通常 `SUM/MIN/MAX/AVG/CNT/CNT_DISTINCT/NUL` |
146
+
147
+ 偏移示例:
148
+
149
+ - `[6,0]` + `DAY`:以基准日期为结束,最近 7 天。
150
+ - `[29,0]` + `DAY`:最近 30 天。
151
+ - `[3,1]` + `MONTH`:基准日期前第 3 个月到前第 1 个月。
152
+ - 动态参数:把对应位置的 `baselineOffset` 置为 `-1`,在 `baselineOffsetDynamicParameters` 写 `[DYNAMIC_PARAMS.xxx]`,同时在顶层 `dynamicParameters` 填默认值。
153
+
154
+ 示例:
155
+
156
+ ```json
157
+ "deriveSetting": {
158
+ "deriveType": "ORDINARY",
159
+ "advType": "RECENT_X",
160
+ "advValue": {
161
+ "advType": "RECENT_X",
162
+ "granularity": "DAY",
163
+ "baseline": "DATE_RANGE_PARAM_RIGHT",
164
+ "baselineOffset": [6, 0],
165
+ "aggrType": "SUM"
166
+ }
167
+ }
168
+ ```
169
+
170
+ ## 累计计算 `XTD`
171
+
172
+ 用于“周/月/季/年至今累计”或“近 N 个粒度累计”。
173
+
174
+ | 字段 | 中文 | 说明 |
175
+ | --- | --- | --- |
176
+ | `advValue.advType` | 高级计算类型 | 固定 `XTD` |
177
+ | `granularity` | 累计范围 | `WEEK/MONTH/QUARTER/YEAR/NONE` |
178
+ | `baseline` | 基准日期 | `DATE_RANGE_PARAM_LEFT` 或 `DATE_RANGE_PARAM_RIGHT` |
179
+ | `baselineOffset` | 自定义累计偏移 | 可选数字;例如 `1` 表示近 2 个粒度累计 |
180
+ | `includeCurrentValue` | 是否包含基准日期当前值 | `true/false` |
181
+
182
+ 示例:月累计:
183
+
184
+ ```json
185
+ "deriveSetting": {
186
+ "deriveType": "ORDINARY",
187
+ "advType": "XTD",
188
+ "advValue": {
189
+ "advType": "XTD",
190
+ "granularity": "MONTH",
191
+ "baseline": "DATE_RANGE_PARAM_RIGHT",
192
+ "includeCurrentValue": true
193
+ }
194
+ }
195
+ ```
196
+
197
+ 限制:基础指标是复合指标时,不支持部分自定义累计方式;特别是“当年累计”这类年累计自定义配置需谨慎,Web 会拦截不支持组合。
198
+
199
+ ## 期末值 `LAST`
200
+
201
+ ```json
202
+ "deriveSetting": {
203
+ "deriveType": "ORDINARY",
204
+ "advType": "LAST",
205
+ "advValue": {
206
+ "advType": "LAST",
207
+ "dateFdId": "<time_fd_id>"
208
+ }
209
+ }
210
+ ```
211
+
212
+ `dateFdId` 必须来自基础指标时间维度。
213
+
214
+ ## 业务限定 `BIZ_CONDITION`
215
+
216
+ 业务限定必须提供顶层 `filter`。
217
+
218
+ ```json
219
+ "deriveSetting": {
220
+ "deriveType": "ORDINARY",
221
+ "advType": "BIZ_CONDITION",
222
+ "advValue": {
223
+ "advType": "BIZ_CONDITION"
224
+ }
225
+ },
226
+ "filter": {
227
+ "combineType": "AND",
228
+ "conditions": []
229
+ }
230
+ ```
231
+
232
+ `filter` 结构复杂时,优先参考同环境已有指标详情或由 Web 配置后复制 payload,不凭空拼复杂筛选。
233
+
234
+ ## 组合衍生 `COMPOSITE`
235
+
236
+ 组合衍生通过公式引用多个指标,不选择单个 `baseMetricId`:
237
+
238
+ ```json
239
+ "deriveSetting": {
240
+ "deriveType": "COMPOSITE",
241
+ "formula": "[<metric_id_1>] / [<metric_id_2>]"
242
+ }
243
+ ```
244
+
245
+ 引用规则:
246
+
247
+ - 涉及组合衍生 `deriveSetting.formula` 时,先读取 `metric-expression-rules.md`。
248
+ - 公式支持 `+`、`-`、`*`、`/`、括号、数字和 `[指标ID]`;不要主动生成函数、窗口函数或 SQL 片段。
249
+ - 可引用原子指标。
250
+ - 可引用普通衍生里的 `RECENT_X`、`XTD`、`LAST`。
251
+ - 不要引用复合指标、组合衍生、快捷引用指标或当前正在编辑的指标。
252
+ - 组合衍生需要公式引用指标存在共有时间维度;没有共有时间维度时 Web 会提示不可配置衍生指标。
253
+
254
+ ## 基础指标选择规则
255
+
256
+ - 普通衍生可衍生自原子指标或复合指标;不能衍生自快捷引用指标。
257
+ - `RECENT_X` 只能衍生自原子指标。
258
+ - `COMPARATIVE` 和 `LAST` 需要基础指标有时间维度。
259
+ - `COMPARATIVE` 可基于最近 N、累计、期末值、组合衍生继续衍生。
260
+ - `BIZ_CONDITION` 可基于非业务限定的任意其它衍生指标。
261
+
262
+ ## 信息收集
263
+
264
+ 如果用户只说“帮我创建一个衍生指标”,先收集:
265
+
266
+ 1. 指标主题和保存目录。
267
+ 2. 衍生类型:同比/环比、最近 N、累计、期末值、业务限定、组合衍生。
268
+ 3. 普通衍生的基础指标,或组合衍生要引用的指标与公式。
269
+ 4. 时间粒度、时间偏移、是否包含当天、数值设置等衍生配置。
270
+ 5. 业务限定的筛选条件 `filter`。
271
+ 6. 数据格式:默认沿用/复制基础指标格式,或指定为数值、货币、百分比;如需指定,确认小数位、千分位、货币符号/前后缀、数量级单位、百分比是否除以 100。
272
+ 7. 指标名称、业务口径、是否保存并上线。
273
+ 8. 责任人和必填 `bizAttrs`。
274
+
275
+ 衍生指标常见做法:
276
+
277
+ - 用户说“跟基础指标格式一样”时,先 `guancli metric get <baseMetricId> -f json` 读取基础指标 `format` 并复制。
278
+ - 同比/环比增长率、转化率、占比类指标通常使用 `PERCENTAGE`。
279
+ - 最近 N、累计、期末值通常复制基础指标 `format`;如果用户没有明确要求,也可以省略 `format` 使用默认。
280
+
281
+ ## JSON 模板:最近 7 天
282
+
283
+ ```json
284
+ {
285
+ "projectId": "<metric_project_id>",
286
+ "subType": "DERIVED",
287
+ "name": "最近7天销售额",
288
+ "engName": "sales_amount_recent_7d",
289
+ "baseMetricId": "<atomic_metric_id>",
290
+ "deriveSetting": {
291
+ "deriveType": "ORDINARY",
292
+ "advType": "RECENT_X",
293
+ "advValue": {
294
+ "advType": "RECENT_X",
295
+ "granularity": "DAY",
296
+ "baseline": "DATE_RANGE_PARAM_RIGHT",
297
+ "baselineOffset": [6, 0],
298
+ "aggrType": "SUM"
299
+ }
300
+ },
301
+ "format": {
302
+ "formatType": "CURRENCY",
303
+ "decimalPlaces": 2,
304
+ "useThousandsSeparator": true,
305
+ "prefix": "¥",
306
+ "prefixUnit": null,
307
+ "showPrefixUnit": true,
308
+ "suffix": ""
309
+ },
310
+ "desc": "统计筛选日期结束日前最近7天的销售额。",
311
+ "parentDirId": "<metric_dir_id>",
312
+ "businessOwner": "<user_id>",
313
+ "publish": false
314
+ }
315
+ ```
316
+
317
+ ## JSON 模板:组合衍生
318
+
319
+ ```json
320
+ {
321
+ "projectId": "<metric_project_id>",
322
+ "subType": "DERIVED",
323
+ "name": "组合衍生客单价",
324
+ "deriveSetting": {
325
+ "deriveType": "COMPOSITE",
326
+ "formula": "[<recent_sales_metric_id>] / [<recent_order_metric_id>]"
327
+ },
328
+ "format": {
329
+ "formatType": "NUMBER",
330
+ "decimalPlaces": 2,
331
+ "useThousandsSeparator": true,
332
+ "prefixUnit": null,
333
+ "showPrefixUnit": true,
334
+ "prefix": "",
335
+ "suffix": ""
336
+ },
337
+ "desc": "使用多个衍生指标组合计算客单价。",
338
+ "parentDirId": "<metric_dir_id>",
339
+ "businessOwner": "<user_id>",
340
+ "publish": false
341
+ }
342
+ ```
343
+
344
+ ## 创建步骤
345
+
346
+ `guancli metric create` 当前是原子指标专用 endpoint;衍生指标创建使用 `guancli fetch`。
347
+
348
+ 1. 生成 `/tmp/derived_metric.json`。
349
+ 2. 本地/人工检查 JSON、基础指标或公式引用指标、时间维度、衍生配置、必填业务属性。
350
+ 3. 按 `metric-common-fields.md` 向用户摘要并确认。
351
+ 4. 用户确认后,不调用原子指标 `save-precheck`;衍生指标 Web 创建没有 save-precheck。
352
+ 5. 提交真实创建:
353
+
354
+ ```bash
355
+ guancli fetch POST /api/metric-platform/metrics/derived-metrics --stdin < /tmp/derived_metric.json
356
+ ```
357
+
358
+ 6. 响应返回指标 ID 后回读确认。
359
+
360
+ ## 编辑步骤
361
+
362
+ 衍生指标没有原子指标的 save-precheck;主要校验基础指标、衍生配置或筛选变化是否影响下游指标/卡片。
363
+
364
+ 1. 读取当前详情:
365
+
366
+ ```bash
367
+ guancli metric get <metric_id> -f json
368
+ ```
369
+
370
+ 2. 基于当前详情生成完整编辑 payload,例如 `/tmp/derived_metric_update.json`。至少包含 `projectId`、`subType`、`name`、`baseMetricId`(普通衍生)、`deriveSetting`、`desc`、`publish`。
371
+ 3. 如果修改了 `baseMetricId`、`deriveSetting` 或 `filter`,先调用影响校验:
372
+
373
+ ```bash
374
+ guancli fetch POST /api/metric-platform/metrics/derived-metrics/<metric_id>/validate-update-impact --stdin < /tmp/derived_metric_update.json
375
+ ```
376
+
377
+ 4. 如果返回 `hasChanged=true` 且 `affectedMetrics` 或 `affectedCards` 非空,展示受影响指标和卡片,等待用户二次确认。
378
+ 5. 提交真实编辑:
379
+
380
+ ```bash
381
+ guancli fetch POST /api/metric-platform/metrics/derived-metrics/<metric_id> --stdin < /tmp/derived_metric_update.json
382
+ ```
383
+
384
+ 6. 保存后回读确认。