> **前置条件** — 执行以下任何命令前，请先确认已完成认证。如未认证，参见 [`../../shb-shared/SKILL.md`](../../shb-shared/SKILL.md)。

# shb-cli event search

事件搜索。

> **本文档出现的命令、子命令、flag、参数名、接口/JSON 字段名，以及取数过程（分页、数量判断、全量拉取、字段裁剪、截断重试）都只供你后台执行，绝不出现在给用户的回复里**——不解释、不转述、不当理由说，换种说法也不行。回复只给业务结果与真实数量（如「共 42 条事件，处理中 7 条」）。

## 搜索事件列表

### 快捷 flag 方式（推荐）

```bash
# 关键字搜索（只匹配事件编号/客户名/联系人姓名/电话，不搜自定义字段）
shb-cli event search --keyword <关键字>

# 按事件类型 ID 筛选
shb-cli event search --template-id <templateId>

# 按状态筛选
shb-cli event search --state <state>

# 分页
shb-cli event search --page 1 --page-size 20

# 组合使用
shb-cli event search --keyword "李四" --state processing --page-size 20

# 格式化数据输出：字段文案和值都会转换为可读内容，可用 --fields 指定字段
shb-cli event search --keyword "李四" --format-data --fields eventNo,state,cusName,executorName,createTime

# 获取全量数据：确定量不大就直接 --all 一次拿齐（>500 或不确定时见「获取全量数据：决策规则」）
shb-cli event search --template-id <templateId> --all --format-data --fields eventNo,state,cusName,createTime
```

### 完整 JSON body 方式

```bash
# 内联 JSON （推荐）
shb-cli event search --data '{"pageNum":1,"pageSize":10,"keyword":"李四","state":"processing"}'

# 从文件读取
shb-cli event search --file ./search.json
```

**使用优先级：快捷 flags ＞ `--data` ＞ `--file`**——常规筛选直接用快捷 flags；需要完整或复杂 JSON（如自定义字段条件 `conditions`）时用 `--data`；`--file` 仅在本地已有现成 JSON 文件时用。

## 格式化数据输出

```bash
shb-cli event search --template-id <templateId> --format-data --fields eventNo,state,cusName,executorName,createTime
shb-cli event search --format-data --fields eventNo,state,cusName,executorName,createTime
shb-cli event search --format-data --include-raw
```

`--format-data` 会把接口原始响应整理为:

- `columns`: 字段 key、字段文案、字段类型
- `rows`: 格式化后的事件列表
- `page`: 分页信息
- `rawRows`: 仅在传 `--include-raw` 时包含

### 支持的搜索字段（JSON body，字段名为 EventSearchModel）

| 字段 | 类型 | 说明 |
|------|------|------|
| `keyword` | string | 关键字搜索，**只**匹配 `eventNo`/`cusName`/`lmName`/`lmPhone`，不搜自定义字段 |
| `pageNum` | int | 页码，**从 1 开始**（默认 1）**——注意字段名是 `pageNum`，不是 `page`**（与工单不同） |
| `pageSize` | int | 每页条数，API 默认 10；全量拉取/统计分析等场景建议设 50 |
| `orderDetail` | string | 排序详情（**不是 `sortBy`**），如 `"isPaused desc, createTime desc"`；不传则用默认排序 |
| `templateId` | string | 事件类型/模板 ID |
| `state` | string | 单个事件状态，传英文 value（见 [`../SKILL.md`](../SKILL.md) 的 State 表），不要传中文 |
| `stateList` | string[] | 多个状态一起查时用；传英文 value 数组 |
| `mySearch` | string | 语义化范围：`create` 我创建 / `execute` 我负责 / `synergy` 我协同 / `all` 综合 / `team` 部门 / `none` 忽略 |
| `cusId` / `lmId` / `productId` | string | 客户/联系人/产品 ID |
| `executor` / `createUser` | string | 负责人/创建人用户 ID |
| `taskNo` | string | 关联工单编号 |
| `isTransferToTask` | string | 是否已转工单 |
| `createTimeStart` / `createTimeEnd` | string | 创建时间范围，格式 `yyyy-MM-dd HH:mm:ss` |
| `updateTimeStart` / `updateTimeEnd` | string | 更新时间范围 |
| `allotTimeStart` / `allotTimeEnd` | string | 分配时间范围 |
| `completeTimeStart` / `completeTimeEnd` | string | 完成时间范围 |
| `conditions` | array | 自定义字段（`attribute`）条件，见下方「自定义字段条件」 |
| `labelQuery` | object | 智能标签过滤，`{"labelIds": number[]\|null, "labelExists": boolean\|null}`。只能通过 `--data`/`--file` 传入，无对应快捷 flag。详见 [`../../shb-label/SKILL.md`](../../shb-label/SKILL.md) |

人员类过滤字段一律传 userId，不要传姓名。当前登录用户的 userId 可通过 `shb-cli config` 查看（chat 场景下系统上下文已提供）。

> **flag 名与 JSON 字段名的对应**：快捷 flag 用**短横线**命名，`--data` 里的 JSON 用**驼峰**命名，二者不可混用。对照：`--page`↔`pageNum`（快捷 flag 叫 `--page`，但写入 body 的字段是 `pageNum`）、`--page-size`↔`pageSize`、`--template-id`↔`templateId`、`--state`↔`state`、`--keyword`↔`keyword`。用 `--data` 时务必写 `"pageNum"` 而**不是** `"page"` 或 `"page-num"`。

#### state 合法值

`state` 过滤时只能传英文 `value`（如 `created` 待分配、`processing` 处理中、`finished` 已完成），**不要传中文或臆造拼写**。完整的 value↔中文标签对照见 [`../SKILL.md`](../SKILL.md) Core Concepts 的 **State（状态）** 表。

#### 自定义字段条件（`conditions`）

用于按自定义字段（`attribute` 中的字段）过滤，元素结构：

```json
{
  "property": "<fieldName>",
  "operator": "eq",
  "value": "某个值"
}
```

`operator` 合法值：`like` `in` `not_in` `between` `eq` `notEq` `gt` `lt` `ge` `le` `is_null` `not_null` `contain` `not_contain` `cascader` `multiSelect` `user` `address` `location` `logistics` `array_contain` `array_eq`。

不同 operator 对应不同的取值字段：

| operator | 取值字段 |
|----------|---------|
| `in` / `not_in` | `inValue`（数组） |
| `between` | `betweenValue1` / `betweenValue2` |
| 数字比较（`gt`/`lt`/`ge`/`le`） | `numberValue` |
| 复杂类型（`cascader`/`user`/`address` 等） | `mapValue` |
| 其余（`eq`/`notEq`/`like`/`contain` 等） | `value` |

示例（自定义字段 `field_priority` 等于"高"）：

```bash
shb-cli event search --data '{
  "templateId": "<templateId>",
  "conditions": [
    {"property": "field_priority", "operator": "eq", "value": "高"}
  ]
}' --format-data
```

字段 key（`fieldName`）不确定时先用 `event field list --type-id <templateId>` 查询。

### 按标签过滤（智能标签）

标签过滤走 `--data`（无快捷 flag），传入 `labelQuery`。**先读 [`../../shb-label/SKILL.md`](../../shb-label/SKILL.md)**——查 labelId、`labelQuery` 字段含义都在那份文档里，这里只给事件场景的示例：

```bash
shb-cli event search --data '{"keyword":"李四","labelQuery":{"labelIds":[12345,67890]}}'
```

## 获取全量数据：决策规则

**全量请求的处理顺序（`--all` 每个查询条件最多执行一次，别重复拉）：**

- **能判断数据量不大（≤500）**——按人 / 按类型 / 按状态的日常查询多属此类——**直接执行一次 `--all`** 拿齐即可，**无需先探量**（`--all` 自带总数与全部数据）。
- **不确定是否会超过 500**（怕一次拉太多被截断）——先用 `pageSize:1` 探一次 `total`（只取 1 条、开销极小），再按下面判断路径；**不要用大 `pageSize` 探一遍后又 `--all` 把数据拉第二遍**。

**判断规则——把 `total` 和 500 直接比大小：**
- `total` ≤ 500（含 500 本身）→ **用 `--all`**（**必须配 `--fields` 收窄列**，见下文「--all 用法」）一次拿齐
- `total` ≥ 501 → **分页叠加**（逐页拉取由模型在上下文中汇总）

> **别把「总条数」当成「总页数」**：`total` 是**事件总条数**，`pages` 是**总页数**（≈ 总条数 ÷ pageSize）。给用户只说条数即可，不要把页数说成条数。

> **注意**：单次输出过大会被截断，能否放下取决于**条数 × 每条字段宽度**。**用 `--format-data --fields` 只取少数列时**，约 500 条以内通常不会截断；若不加 `--format-data`（输出接口原始响应、含全部字段）或不限字段，几百条甚至更少就可能被截断。所以 `--all` 必须配 `--format-data --fields`，超出就改分页叠加。

### --all 用法

```bash
shb-cli event search --template-id <templateId> --state created --all \
  --format-data --fields eventNo,state,cusName,executorName,createTime
```

> **`--all` 用法要点：**
> - **必须 `--format-data --fields <少数列>` 两者一起**才能收窄输出。⚠️ `--fields` **只在 `--format-data` 下生效**：不加 `--format-data` 时 CLI 输出的是**接口原始响应（含全部字段）**，`--fields` 被忽略、输出必然很大被截断；也**不要加 `--include-raw`**（它会把全字段原始行塞回来）。
> - **每个查询条件最多执行一次**：`--all` 已遍历所有页、返回完整结果与总数，**不要再补跑分页、也不要再次 `--all`**。
> - 只为拿 `total` 决定路径时，用 `pageSize:1` 探一次即可，**别用大 `pageSize` 探一遍后又 `--all` 把数据拉第二遍**。
> - 结果若因体积被截断，改用分页叠加，而非反复重试 `--all`。

## 典型组合场景

### 场景一：查看某事件类型下指定状态的事件（以「待分配」为例）

先通过 `event type list` 拿到 templateId，再按数量决定拉取策略：

```bash
# 1. 查出可用事件类型
shb-cli event type list --list-type writeList --format-data

# 2. 取全部
shb-cli event search --template-id <templateId> --state created --all \
  --format-data --fields eventNo,state,cusName,executorName,createTime
```

---

### 场景二：按关键字搜索事件并查看详情

```bash
# 1. 用事件编号或客户名关键字搜索，从返回结果中读取目标事件的 id
shb-cli event search --keyword "E-20260101" --format-data --fields eventNo,id,state,cusName

# 2. 查看该事件完整详情
shb-cli event detail --id <eventId>
```

> 若本轮对话中已经搜索过该事件（列表里出现过它的 `id`），**直接复用已有 id 调 detail，不要重新 search**（见 SKILL.md「复用已知 ID」）。

---

### 场景三：查询我负责 / 我创建的事件

```bash
shb-cli event search --data '{"mySearch":"execute"}' --all \
  --format-data --fields eventNo,state,cusName,executorName,createTime
```

> 「我创建的事件」把 `execute` 换成 `create`，「我协同的事件」换成 `synergy`。

---

### 场景四：按时间范围查询事件

时间格式为 `yyyy-MM-dd HH:mm:ss`：

```bash
shb-cli event search --data '{
  "templateId": "<templateId>",
  "createTimeStart": "2026-01-01 00:00:00",
  "createTimeEnd": "2026-03-31 23:59:59"
}' --all --format-data --fields eventNo,state,cusName,createTime
```

---

### 场景五：统计各状态事件数量

每个状态单独查一次，`pageSize` 设 1 只为拿到 `page.totalElements`（即该状态总数），由模型逐条调用并汇总。**不要用 `for` 循环或 `;` 串联多条命令**——headless 模式下 shell 仅允许单条 shb-cli 命令。

```bash
shb-cli event search --data '{"templateId":"<templateId>","state":"created","pageNum":1,"pageSize":1}' --format-data
shb-cli event search --data '{"templateId":"<templateId>","state":"processing","pageNum":1,"pageSize":1}' --format-data
shb-cli event search --data '{"templateId":"<templateId>","state":"finished","pageNum":1,"pageSize":1}' --format-data
# … 其余状态同理，模型读取各自 page.totalElements 后汇总
```

> 汇总展示给用户时**只用中文标签**，不要在后面附英文 value：写「处理中：7」而**不是**「处理中(processing)：7」。

---

## --format-data 输出结构速查

`--format-data -o raw` 返回：

```json
{
  "page":    {"page": 1, "pageSize": 10, "totalElements": 42, "totalPages": 5},
  "columns": [{"field": "eventNo", "label": "事件编号"}, ...],
  "rows":    [{"eventNo": "E-...", "state": "已完成", "cusName": "南图测试客户", "templateName": "上门维修", ...}, ...]
}
```

> `page` 排在最前是有意为之：结果很大被截断时，开头的总量信息仍能保留，便于据此决定分页策略。

`rows` 中每条记录的常用字段（值已格式化为中文可读内容）——不加 `--fields` 时默认只输出前一批「基础字段」；其余字段（时间类/状态类/其它）需显式在 `--fields` 中指定才会出现：

### 基础字段

| 字段 | 说明 | 备注 |
|------|------|------|
| `eventNo` | 事件编号 | |
| `templateName` | 事件类型名称 | **直接可读，无需再查 `event type list`** |
| `state` | 事件状态（中文） | 若事件处于暂停中，无论原始状态是什么都会显示为「暂停中」 |
| `cusName` | 客户名称 | **直接可读**；已自动去除后端返回的链接标记 |
| `address` | 客户地址 | 省市区+详细地址拼接 |
| `lmName` / `lmPhone` | 联系人姓名/电话 | |
| `product` | 产品名称 | 多个产品以顿号分隔 |
| `executorName` | 负责人姓名 | |
| `synergies` | 协同人姓名 | 多人以逗号分隔 |
| `createUserName` | 创建人姓名 | |
| `source` | 创建方式 | 已是中文（如"手动创建"），无需再转换 |
| `taskNo` | 关联工单编号 | 一个事件可能关联多个工单，多个以顿号分隔 |
| `degree` | 满意度 | 值本身即中文（如"满意"），无需再转换 |

### 时间类字段

| 字段 | 说明 |
|------|------|
| `createTime` | 创建时间，格式 `YYYY-MM-DD HH:mm:ss`，取前 7 位即得 `YYYY-MM` |
| `allotTime` | 分配时间 |
| `startTime` | 开始处理时间 |
| `completeTime` | 完成时间 |
| `updateTime` | 最近更新时间 |
| `planStartTime` / `planEndTime` | 计划开始/结束时间 |
| `evaluateTime` | 评价时间 |
| `reviewTime` | 回访时间 |
| `acceptUsedTimeStr` | 响应用时（已格式化，如"2小时30分钟"） |
| `workUsedTimeStr` | 工作用时（已格式化） |
| `finishUsedTimeStr` | 完成用时（已格式化） |

### 状态/标记类字段（是/否、已/未）

| 字段 | 说明 |
|------|------|
| `isTransferToTask` | 是否已转工单：`是` / `否` |
| `onceRollback` | 曾回退：`是` / `否` |
| `onceTransferred` | 曾转派：`是` / `否` |
| `inApprove` | 审批状态：`审批中` / `未审批` |
| `isEvaluate` | 评价状态：`已评价` / `未评价` |
| `reviewerState` | 回访状态：`已回访` / `未回访` |

### 其它

| 字段 | 说明 |
|------|------|
| `tagEvaluates` | 服务标签（来自评价记录） |
| `suggestion` | 客户建议/意见 |

自定义字段（`--fields` 传 `field_xxx` 这类 key）也会一并格式化，标签来自该事件类型的字段定义（见 [`shb-event-field.md`](shb-event-field.md)）。

---

## 注意

- `event search` 默认输出原始响应；需要字段文案和值格式化时显式传 `--format-data`。
- `--format-data` 未指定 `--fields` 时，会优先使用字段元数据里的可见字段；取不到字段元数据时使用内置常用字段。用户只需要少数字段时，显式传 `--fields`。
- 搜索结果为空时，检查 `templateId` 和 `state` 是否匹配当前租户下实际存在的值。
- 查询自己或他人的信息时请传 userId，不要传姓名。
- **统计 / 报告优先聚合计数**：按状态/类型/月度等做分布统计时，用计数查询（每维度 `pageSize:1` 取 `total`，见场景五）拿数量后汇总，**不要为了数数把全量明细拉进来**——零截断、不占上下文。
- **全量 / 大量数据（确需明细时）**：拉取策略统一见「获取全量数据：决策规则」；逐页一律用 `--format-data --fields` 收窄字段。
