Skillshap-v3-api
H

hap-v3-api

使用明道云 HAP V3 接口搭建页面和操作数据的专业技能。当用户提到"HAP V3 接口"、"HAP API"、"接口调用"、"数据接口"、"Appkey"、"Sign"、"接口鉴权"等需求时,必须使用此技能。此技能提供完整的 HAP V3 接口使用指南:鉴权配置、接口调用、筛选器使用、数据操作等。如果用户已配置 HAP MCP,AI 应该自动从 MCP 配置中提取鉴权密钥。

garfield-bb
9 stars
1.2k downloads
Updated 1w ago

Readme

hap-v3-api follows the SKILL.md standard. Use the install command to add it to your agent stack.

---
name: hap-v3-api
description: 使用明道云 HAP V3 接口搭建页面和操作数据的专业技能。当用户提到"HAP V3 接口"、"HAP API"、"接口调用"、"数据接口"、"Appkey"、"Sign"、"接口鉴权"等需求时,必须使用此技能。此技能提供完整的 HAP V3 接口使用指南:鉴权配置、接口调用、筛选器使用、数据操作等。如果用户已配置 HAP MCP,AI 应该自动从 MCP 配置中提取鉴权密钥。
license: MIT
---

# HAP V3 API 使用技能

此技能提供使用明道云 HAP V3 接口搭建页面、实时获取数据和操作数据的完整指南。

## Overview

明道云 HAP (High-performance Application Platform) 是一个超级应用平台,通过这个基座可以搭建很多应用。通过 HAP V3 接口,您可以:

1. **在自定义视图插件中**调用 V3 接口操作数据
2. **在独立前端页面中**使用 V3 接口编排业务逻辑
3. **实时获取和操作**明道云应用中的数据

**核心能力:**
- ✅ 完整的 API 使用工作流(从零搭建应用到数据操作)
- ✅ 详细的字段类型处理规范
- ✅ Filter 筛选器完整语法
- ✅ 关联字段深度查询指南
- ✅ 常见陷阱和解决方案
- ✅ 性能优化最佳实践

**详细文档:** 参考 `references/hap-api-usage-guide.md` 获取完整的 API 使用规范

---

## ⚠️ 重要:何时使用此技能

**使用优先级规则**:

### 优先级 1: 已配置 HAP MCP → 直接使用 MCP 工具 ✅

如果用户已经配置了 HAP 应用执行 MCP,AI 应该**直接使用 MCP 工具**,而不是编写 API 请求代码。

**MCP 工具优势**:
- ✅ 无需手动处理鉴权
- ✅ 无需编写请求代码
- ✅ MCP 工具自动处理所有细节
- ✅ 更简洁、更可靠

**可用的 MCP 工具**:
- `get_app_info` - 获取应用信息
- `get_app_worksheets_list` - 获取工作表列表
- `get_worksheet_structure` - 获取工作表结构
- `get_record_list` - 查询记录列表
- `get_record_pivot_data` - 获取透视表数据
- `create_record` - 创建记录
- `update_record` - 更新记录
- `delete_record` - 删除记录
- `batch_create_records` - 批量创建记录
- `batch_update_records` - 批量更新记录
- `batch_delete_records` - 批量删除记录
- 等等...(完整列表请参考 MCP 工具文档)

**示例 - 使用 MCP 工具查询数据**:
```javascript
// ✅ 正确 - 直接使用 MCP 工具
const records = await mcpClient.call('get_record_list', {
  worksheet_id: 'xxx',
  pageSize: 100,
  pageIndex: 1,
  filter: {
    type: 'group',
    logic: 'AND',
    children: [
      {
        type: 'condition',
        field: 'status',
        operator: 'eq',
        value: ['已成交']
      }
    ]
  }
});

// ❌ 错误 - 不要编写 API 请求代码
// fetch('https://api.mingdao.com/v3/open/worksheet/getFilterRows', ...)
```

### 优先级 2: 仅在以下情况使用 HAP V3 API 编写代码

**何时使用 V3 API 代码**:
1. ✅ 用户**明确需要编写代码实现**(如在视图插件、独立前端项目中集成)
2. ✅ 用户需要在代码中**编排复杂的业务逻辑**
3. ✅ **未配置 HAP MCP** 或 MCP 不可用

**示例场景**:
- "帮我在 React 组件中集成 HAP API 查询数据" → ✅ 使用 V3 API 代码
- "帮我写一个函数,批量导入数据到 HAP" → ✅ 使用 V3 API 代码
- "帮我查询客户管理表中的数据"(已配置 MCP)→ ❌ 不要写代码,使用 MCP 工具

---

## 快速开始

### 0. HAP 产品线说明 ⚠️

HAP 支持多个产品线和私有部署,**API Host 配置不同**:

| 产品线 | API Host | 说明 |
|--------|----------|------|
| **明道云 HAP** | `https://api.mingdao.com` | 官方 SaaS 服务 |
| **Nocoly HAP** | `https://www.nocoly.com` | Nocoly SaaS 服务 |
| **私有部署 HAP** | `https://your-domain.com/api` | ⚠️ **注意:私有部署需要在域名后加 `/api`** |

**示例**:
- 明道云:`https://api.mingdao.com/v3/open/worksheet/getFilterRows`
- Nocoly:`https://www.nocoly.com/v3/open/worksheet/getFilterRows`
- 私有部署:`https://p-demo.mingdaoyun.cn/api/v3/open/worksheet/getFilterRows` ← 注意 `/api`

**AI 必须根据用户的 MCP 配置自动判断使用哪个 host**。如果用户未提供 MCP 配置,需询问使用哪个产品线。

---

### 1. 获取 API 凭证

**方法一: 从 MCP 配置中提取(推荐)**

如果用户已经配置了 HAP 应用执行 MCP,AI 助手应该**自动从 MCP 配置中提取鉴权密钥**,而不是让用户手动输入。

**⚠️ 重要**: AI 必须**自动检测用户当前使用的 IDE**,然后读取对应的配置文件。不要假设用户使用 Cursor。

#### 自动化提取步骤

**Step 1: 自动检测当前使用的 IDE 平台**

AI 必须**自动检测**用户当前使用的 IDE,不要假设或询问。检测方法(按优先级):

1. **检测当前运行的 IDE**(最高优先级)
   - 检查环境变量:`$TERM_PROGRAM`(可能值:`cursor`, `claude`, `trae` 等)
   - 检查会话变量:`$CLAUDE_SESSION`, `$TRAE_SESSION`, `$ANTIGRAVITY_SESSION` 等
   - 检查进程:`pgrep -x "Cursor"`, `pgrep -x "Claude"` 等

2. **检查已安装的 IDE**(如果第1步失败)
   - 检查配置目录:`~/.cursor`, `~/.claude`, `~/.trae` 等是否存在
   - 如果检测到多个,按流行度选择:Cursor → Claude Code → TRAE → 其他

3. **检查项目级配置**(如果前2步失败)
   - 检查当前项目目录:`.cursor/`, `.trae/`, `.claude/` 等

**支持的 IDE 平台和配置路径**:

| IDE 平台 | 全局配置文件路径 | 项目级配置路径 |
|---------|----------------|--------------|
| **Claude Code** | `~/.claude/config.json` 或通过 `claude mcp list` 命令 | `.claude/config.json` |
| **Cursor** | `~/.cursor/mcp.json` 或 `~/Library/Application Support/Cursor/User/settings.json` (macOS) | `.cursor/mcp.json` |
| **TRAE** | `~/.trae/mcp.json` | `.trae/mcp.json` |
| **GitHub Copilot** | `~/.copilot/mcp.json` | `.github/mcp.json` |
| **Antigravity** | `~/.gemini/antigravity/config.json` | `.agent/config.json` |
| **OpenCode** | `~/.config/opencode/mcp.json` | `.opencode/mcp.json` |
| **Windsurf** | `~/.codeium/windsurf/mcp.json` | `.windsurf/mcp.json` |
| **Gemini CLI** | `~/.gemini/config.json` | `.gemini/config.json` |
| **Codex** | `~/.codex/config.toml` | `.codex/config.toml` |
| **Manus** | `~/.manus/mcp.json` | - |
| **Coze** | `~/.coze/mcp_config.json` | - |

**Step 2: 读取对应平台的 MCP 配置文件**

根据检测到的平台,读取对应的配置文件。

**Step 3: 查找 HAP MCP 配置**

- 在配置对象中查找以 `hap-mcp-` 开头的服务器配置
- 识别应用执行 MCP(包含 `url` 字段且 URL 指向 `api.mingdao.com/mcp`)

**MCP 配置格式示例**:
```json
{
  "mcpServers": {
    "hap-mcp-应用名": {
      "url": "https://api.mingdao.com/mcp?HAP-Appkey=6802bfa5da37d75f&HAP-Sign=MWZmZWU1YmMyMzE4ZTAxYjY3NTViYjM5NzhlNTdhOTIwZWFhYTc2Y2I2YzljNWMzNDFmMjk4NTM2N2M0YTg2OA=="
    }
  }
}
```

**Step 4: 从 URL 中解析鉴权参数**

- 从 URL 的查询参数中提取 `HAP-Appkey` 的值
- 从 URL 的查询参数中提取 `HAP-Sign` 的值
- 注意:URL 参数可能经过 URL 编码,需要正确解码

#### 代码示例(AI 助手操作)

```javascript
// 1. 检测当前使用的 IDE 平台
function detectCurrentIDE() {
  // 检查环境变量
  const termProgram = process.env.TERM_PROGRAM;
  if (termProgram === 'cursor') return 'cursor';
  if (termProgram === 'claude') return 'claude';
  if (termProgram === 'trae') return 'trae';

  // 检查会话变量
  if (process.env.CLAUDE_SESSION) return 'claude';
  if (process.env.TRAE_SESSION) return 'trae';
  if (process.env.ANTIGRAVITY_SESSION) return 'antigravity';

  // 检查已安装的 IDE(降级检查)
  const homeDir = process.env.HOME || process.env.USERPROFILE;
  if (fs.existsSync(path.join(homeDir, '.cursor', 'mcp.json'))) return 'cursor';
  if (fs.existsSync(path.join(homeDir, '.claude', 'config.json'))) return 'claude';
  if (fs.existsSync(path.join(homeDir, '.trae', 'mcp.json'))) return 'trae';

  // 默认使用 Cursor(最流行)
  return 'cursor';
}

// 2. 根据 IDE 获取配置文件路径
function getConfigPath(ide) {
  const homeDir = process.env.HOME || process.env.USERPROFILE;

  const configPaths = {
    'cursor': path.join(homeDir, '.cursor', 'mcp.json'),
    'claude': path.join(homeDir, '.claude', 'config.json'),
    'trae': path.join(homeDir, '.trae', 'mcp.json'),
    'copilot': path.join(homeDir, '.copilot', 'mcp.json'),
    'antigravity': path.join(homeDir, '.gemini', 'antigravity', 'config.json'),
    'opencode': path.join(homeDir, '.config', 'opencode', 'mcp.json'),
    'windsurf': path.join(homeDir, '.codeium', 'windsurf', 'mcp.json'),
    'gemini': path.join(homeDir, '.gemini', 'config.json'),
    'codex': path.join(homeDir, '.codex', 'config.toml'),
    'manus': path.join(homeDir, '.manus', 'mcp.json'),
    'coze': path.join(homeDir, '.coze', 'mcp_config.json')
  };

  return configPaths[ide];
}

// 3. 读取并解析配置
const currentIDE = detectCurrentIDE();
const configPath = getConfigPath(currentIDE);

if (!fs.existsSync(configPath)) {
  console.log(`未找到 ${currentIDE} 的 MCP 配置文件`);
  return;
}

const configContent = fs.readFileSync(configPath, 'utf8');
const config = JSON.parse(configContent);

// 4. 查找 HAP MCP 配置
const mcpServers = config.mcpServers || {};
const hapMcpConfig = Object.entries(mcpServers).find(
  ([name, config]) => name.startsWith('hap-mcp-') && config.url
);

if (hapMcpConfig) {
  const [mcpName, mcpConfig] = hapMcpConfig;
  const url = new URL(mcpConfig.url);

  // 5. 提取 Appkey 和 Sign
  const appkey = url.searchParams.get('HAP-Appkey');
  const sign = url.searchParams.get('HAP-Sign');

  console.log(`✅ 从 ${currentIDE} 的 MCP 配置中提取到鉴权信息`);
  console.log('MCP 名称:', mcpName);
  console.log('Appkey:', appkey);
  console.log('Sign:', sign);
} else {
  console.log(`未找到 HAP MCP 配置,请先配置 MCP 或手动输入鉴权信息`);
}
```

#### 实际操作流程

当用户需要调用 HAP API 时,AI 应该:

1. **检查是否已配置 MCP**
   - 读取 Cursor 全局设置文件
   - 查找 `hap-mcp-*` 配置

2. **提取鉴权信息**
   - 如果找到 MCP 配置,自动从 URL 中提取 Appkey 和 Sign
   - 如果找到多个 MCP 配置,询问用户使用哪个应用

3. **使用提取的密钥**
   - 在 API 请求头中使用提取的 `HAP-Appkey` 和 `HAP-Sign`
   - 如果提取失败,提示用户手动提供或检查 MCP 配置

#### 注意事项

- ✅ **优先使用 MCP 配置**: 如果用户已配置 MCP,优先从配置中提取
- ✅ **URL 解码**: 注意 URL 参数可能经过编码,需要正确解码
- ✅ **多个应用**: 如果配置了多个 HAP MCP,询问用户使用哪个应用
- ⚠️ **配置不存在**: 如果未找到 MCP 配置,提示用户先配置 MCP 或手动提供密钥
- ⚠️ **权限问题**: 如果无法读取配置文件,提示用户检查文件权限

**方法二: 手动获取**

如果用户未配置 MCP 或需要手动提供:

1. 登录明道云 → 应用 → 设置 → API 密钥
2. 复制 Appkey 和 Sign
3. 或提供 MCP 配置信息,让 AI 自动提取

### 2. 配置请求头

所有 HAP V3 API 请求都需要以下请求头:

```javascript
const headers = {
  'Content-Type': 'application/json',
  'HAP-Appkey': 'your-app-key',
  'HAP-Sign': 'your-sign-key'
};
```

**⚠️ 注意:** 请求头使用 `HAP-Appkey` 和 `HAP-Sign`(不是 `AppKey` 和 `Sign`)

### 3. 获取 API 文档

**使用 Apifox MCP Server(推荐):**

```json
{
  "应用 API - API 文档": {
    "command": "npx",
    "args": [
      "-y",
      "apifox-mcp-server@latest",
      "--site-id=5442569"
    ]
  }
}
```

**在线文档资源:**
- [API 整体介绍](https://apifox.mingdao.com/7271706m0.md)
- [字段类型对照表](https://apifox.mingdao.com/7271709m0.md)
- [筛选器使用指南](https://apifox.mingdao.com/7271713m0.md)
- [错误码说明](https://apifox.mingdao.com/7271715m0.md)

---

## 核心工作流程

### 阶段一: 准备工作

**Step 1: 获取 API 凭证**
- **优先方式**: 从 Cursor MCP 配置中自动提取 Appkey 和 Sign(如果用户已配置)
- **备选方式**: 从 HAP 后台手动获取或让用户提供

**Step 2: 配置 API 请求头**
- 使用提取或提供的 Appkey 和 Sign 设置请求头
- 设置 `HAP-Appkey` 和 `HAP-Sign` 请求头

### 阶段二: 创建应用结构

**Step 3: 获取应用信息(可选)**
```javascript
GET /v3/app/info
```

**Step 4: 创建工作表**
```javascript
POST /v3/app/worksheets
{
  "name": "客户信息表",
  "alias": "customers",
  "fields": [
    {
      "name": "客户名称",
      "alias": "customer_name",
      "type": "Text",
      "isTitle": true,
      "required": true
    }
  ]
}
```

**详细规范:** 参考 `references/hap-api-usage-guide.md` 第 1 节

### 阶段三: 填充数据

**Step 5: 准备选项字段映射**
- 对于单选/多选字段,需要先获取选项的 key(UUID)
- 查询工作表结构获取 options 列表

**Step 6: 创建记录**
```javascript
POST /v3/app/worksheets/{worksheet_id}/rows
{
  "fields": [
    {
      "id": "customer_name",
      "value": "明道云科技有限公司"
    },
    {
      "id": "customer_type",
      "value": ["74c7b607-864d-4cc4-b401-28acba2636e9"]  // ⚠️ 使用选项key
    }
  ],
  "triggerWorkflow": true
}
```

**关键点:**
- ⚠️ 选项字段必须用 key,不能用显示文本
- ⚠️ 选项字段即使单选也要用数组格式
- ✅ 数值字段写入时传数字,读取时返回字符串

**详细规范:** 参考 `references/hap-api-usage-guide.md` 第 3 节

### 阶段四: 查询和分析数据

**Step 7: 查询记录列表**
```javascript
POST /v3/app/worksheets/{worksheet_id}/rows/list
{
  "filter": {
    "type": "group",
    "logic": "AND",
    "children": [
      {
        "type": "condition",
        "field": "customer_type",
        "operator": "eq",
        "value": ["74c7b607-864d-4cc4-b401-28acba2636e9"]  // 使用key
      }
    ]
  },
  "sorts": [{
    "field": "annual_budget",
    "isAsc": false
  }],
  "pageIndex": 1,
  "pageSize": 20
}
```

**详细规范:** 参考 `references/hap-api-usage-guide.md` 第 4 节

---

## Filter 筛选器规范 ⭐重点

### Filter 对象结构

**基础结构:**
```typescript
Filter = {
  type: 'group' | 'condition';
  
  // type='group' 时的字段
  logic?: 'AND' | 'OR';
  children?: Filter[];  // 子条件,最多两层嵌套
  
  // type='condition' 时的字段
  field?: string;       // 字段ID或别名
  operator?: string;    // 操作符
  value?: any[];        // 值数组
}
```

**规则:**
1. 顶层必须是 `group` 类型
2. 最多两层嵌套: group → group → condition
3. 同一 group 的 children 必须类型一致
4. group 必须指定 `logic` (AND/OR)
5. condition 必须指定 `field`, `operator`

### 操作符完整列表

| 操作符 | 说明 | 需要value | value格式 | 适用字段 |
|-------|------|----------|----------|---------|
| `eq` | 等于 | ✅ | `["值"]` | 所有类型 |
| `ne` | 不等于 | ✅ | `["值"]` | 所有类型 |
| `contains` | 包含 | ✅ | `["值"]` | Text, MultipleSelect |
| `notcontains` | 不包含 | ✅ | `["值"]` | Text, MultipleSelect |
| `startswith` | 开头是 | ✅ | `["值"]` | Text |
| `endswith` | 结尾是 | ✅ | `["值"]` | Text |
| `gt` | 大于 | ✅ | `["值"]` | Number, Date |
| `gte` | 大于等于 | ✅ | `["值"]` | Number, Date |
| `lt` | 小于 | ✅ | `["值"]` | Number, Date |
| `lte` | 小于等于 | ✅ | `["值"]` | Number, Date |
| `between` | 介于之间 | ✅ | `["最小值", "最大值"]` | Number, Date |
| `isempty` | 为空 | ❌ | 不需要 | 所有类型 |
| `isnotempty` | 不为空 | ❌ | 不需要 | 所有类型 |
| `belongsto` | 属于 | ✅ | `["ID1", "ID2"]` | Relation, Department |
| `in` | 在...中 | ✅ | `["值1", "值2"]` | 所有类型 |
| `concurrent` | 同时包含 | ✅ | `["值1", "值2"]` | MultipleSelect |

### 筛选示例

**示例1: 单选字段筛选(⚠️ 必须使用 key)**
```javascript
{
  "type": "group",
  "logic": "AND",
  "children": [{
    "type": "condition",
    "field": "customer_type",
    "operator": "eq",
    "value": ["74c7b607-864d-4cc4-b401-28acba2636e9"]  // ✅ 使用key
  }]
}

// ❌ 错误: value: ["成交客户"]  // 不能用显示文本!
```

**示例2: 数值范围筛选(⚠️ value 必须是字符串数组)**
```javascript
{
  "type": "condition",
  "field": "annual_budget",
  "operator": "between",
  "value": ["500000", "2000000"]  // ✅ 字符串数组
}

// ❌ 错误: value: [500000, 2000000]  // 不能用数字!
```

**示例3: 关联字段筛选(⚠️ 必须用 belongsto)**
```javascript
{
  "type": "condition",
  "field": "related_customer",
  "operator": "belongsto",  // ✅ 关联字段用 belongsto
  "value": ["customer-row-id"]
}

// ❌ 错误: operator: "eq"  // 关联字段不支持 eq!
```

**详细规范:** 参考 `references/hap-api-usage-guide.md` 第 4 节

---

## 字段类型处理规范

### 关键字段类型处理

#### 1. 选项字段(SingleSelect/MultipleSelect)⭐⭐⭐

**写入:** 必须传选项 key 的数组
```javascript
{
  "id": "customer_type",
  "value": ["74c7b607-864d-4cc4-b401-28acba2636e9"]  // 选项key
}
```

**读取:** 返回包含 key 和 value 的对象数组
```javascript
{
  "customer_type": [
    {
      "key": "74c7b607-864d-4cc4-b401-28acba2636e9",
      "value": "成交客户"
    }
  ]
}
```

**⚠️ 关键点:**
- 即使是单选,也要用数组 `["key"]`
- 不能传显示文本 `["成交客户"]`,必须用 key
- 筛选时必须使用 key,不能使用显示文本

#### 2. 附件字段(Attachment)⭐

**写入:** 支持 URL 和 base64
```javascript
{
  "id": "attachments",
  "type": "0",  // 0=覆盖, 1=追加
  "value": [{
    "name": "产品宣传册.pdf",
    "url": "https://example.com/brochure.pdf"
  }]
}
```

**读取:** 返回附件对象数组
```javascript
{
  "attachments": [{
    "file_id": "...",
    "file_name": "...",
    "downloadUrl": "https://...",  // ⚠️ 使用 downloadUrl
    "file_size": 2048576
  }]
}
```

**⚠️ 重要提示:**
- 附件上传是异步处理,通常需要 5-10 秒
- API 返回成功不代表附件已上传完成
- 使用 `downloadUrl` 而非 `url`

#### 3. 关联字段(Relation)⭐⭐⭐

**写入:** 传记录 ID 数组
```javascript
{
  "id": "related_customer",
  "value": ["945e6503-3823-4e91-9d84-a53f8bdd6fc5"]  // 记录rowid
}
```

**读取:** 返回对象数组(只包含 sid 和 name)
```javascript
{
  "related_customer": [{
    "sid": "945e6503-3823-4e91-9d84-a53f8bdd6fc5",
    "name": "明道云科技有限公司"
  }]
}
```

**获取完整关联数据:**
```javascript
// 方法1: 使用专用 API
GET /v3/app/worksheets/{worksheet_id}/rows/{row_id}/relations/{field_id}

// 方法2: 使用 sid 查询目标表
POST /v3/app/worksheets/{target_worksheet_id}/rows/list
{
  "filter": {
    "type": "group",
    "logic": "AND",
    "children": [{
      "type": "condition",
      "field": "rowid",  // ⚠️ 使用系统字段 rowid
      "operator": "in",
      "value": ["sid1", "sid2"]  // 传入关联记录的 sid
    }]
  }
}
```

**详细规范:** 参考 `references/hap-api-usage-guide.md` 第 6 节

#### 4. 成员字段(Collaborator)

**写入:** 传用户 ID 数组
```javascript
{
  "id": "owner",
  "value": ["user-account-id-123"]  // 用户ID,不是用户名
}
```

**获取用户ID:**
```javascript
POST /v3/users/lookup
{
  "name": "张三"  // 精确匹配姓名
}
```

#### 5. 数值字段(Number)

**写入:** 传数字类型
```javascript
{
  "id": "annual_budget",
  "value": 1000000.50
}
```

**读取:** 返回字符串
```javascript
{
  "annual_budget": "1000000.50"
}
```

**⚠️ 注意:** 写入数字,读取字符串

**详细规范:** 参考 `references/hap-api-usage-guide.md` 第 2、3 节

---

## triggerWorkflow 参数详解 ⭐重要

`triggerWorkflow` 参数控制是否在数据操作时触发工作表相关的工作流。

**适用范围:**
- ✅ 创建记录
- ✅ 批量创建
- ✅ 更新记录
- ✅ 批量更新
- ✅ 删除记录
- ✅ 批量删除

**参数说明:**

| 参数值 | 说明 | 默认值 | 使用场景 |
|-------|------|--------|---------|
| `true` | 触发工作流 | ✅ 是 | 正常业务操作,需要执行自动化流程 |
| `false` | 不触发工作流 | ❌ 否 | 数据迁移、批量初始化、测试数据 |

**✅ 应该设置为 `true` 的场景:**
- 正常业务操作(用户提交表单、更新状态等)
- 需要自动化处理的操作

**❌ 应该设置为 `false` 的场景:**
- 数据迁移和导入
- 批量数据初始化
- 定时同步任务
- 测试和调试

**性能影响:**
- `triggerWorkflow: false` - API 响应快,通常 < 500ms
- `triggerWorkflow: true` - 需要等待工作流执行,可能需要 1-5 秒

**详细说明:** 参考 `references/hap-api-usage-guide.md` 第 3.2 节

---

## 常见陷阱与解决方案 ⭐⭐⭐

### 陷阱1: 选项字段筛选使用显示文本

**问题:** 筛选单选/多选字段时返回空结果

**错误示例:**
```javascript
{
  "field": "customer_type",
  "operator": "eq",
  "value": ["成交客户"]  // ❌ 使用了显示文本
}
```

**正确做法:**
```javascript
{
  "field": "customer_type",
  "operator": "eq",
  "value": ["74c7b607-864d-4cc4-b401-28acba2636e9"]  // ✅ 使用选项key
}
```

**解决方案:**
1. 初始化时查询工作表结构,缓存选项映射
2. 或先查询一条记录,从返回数据获取 key
3. 建立 value → key 的映射表

### 陷阱2: 数值字段筛选使用数字类型

**问题:** 数值筛选无结果或报错

**错误示例:**
```javascript
{
  "field": "annual_budget",
  "operator": "gt",
  "value": [1000000]  // ❌ 数字类型
}
```

**正确做法:**
```javascript
{
  "field": "annual_budget",
  "operator": "gt",
  "value": ["1000000"]  // ✅ 字符串数组
}
```

**记忆口诀:** 筛选条件的 value 永远是字符串数组

### 陷阱3: 关联字段使用错误的操作符

**问题:** 使用错误的操作符筛选关联字段

**错误示例:**
```javascript
{
  "field": "related_customer",
  "operator": "eq",  // ❌ 关联字段不支持 eq
  "value": ["customer-id"]
}
```

**正确做法:**
```javascript
{
  "field": "related_customer",
  "operator": "belongsto",  // ✅ 使用 belongsto
  "value": ["customer-id"]
}
```

### 陷阱4: 关联字段 N+1 查询问题

**问题:** 在列表页逐个查询关联数据

**错误示例:**
```javascript
// ❌ 性能灾难:100个产品 = 1 + 100 = 101次请求
const products = await getProductList();  // 1次请求

for (const product of products) {
  const categoryId = product.category[0].sid;
  const category = await getCategoryById(categoryId);  // 100次请求!
}
```

**正确做法:** 批量查询
```javascript
// ✅ 性能优化:100个产品 = 1 + 1 = 2次请求
const products = await getProductList();  // 1次请求

// 收集所有分类ID
const categoryIds = new Set();
products.forEach(p => {
  if (p.category && p.category.length > 0) {
    categoryIds.add(p.category[0].sid);
  }
});

// 批量查询所有分类
const categories = await getRows('category-worksheet-id', {
  filter: {
    type: 'condition',
    field: 'rowid',
    operator: 'in',
    value: Array.from(categoryIds)
  }
});  // 1次请求

// 建立映射
const categoryMap = {};
categories.rows.forEach(cat => {
  categoryMap[cat.rowid] = cat;
});
```

**详细说明:** 参考 `references/hap-api-usage-guide.md` 第 7 节

---

## 性能优化建议

### 1. 查询优化

- **合理使用分页**: pageSize 不要超过 1000
- **指定返回字段**: 使用 fields 参数,只返回需要的字段
- **使用字段ID**: 比别名查询性能更好
- **避免过度嵌套**: Filter 嵌套控制在 2 层以内
- **善用视图**: 复杂筛选可先创建视图,再查询视图

### 2. 批量操作优化

- **批量创建**: 一次最多 100 条
- **批量更新**: 一次最多 100 条
- **包含关联字段**: 减少到每批 30-50 条
- **包含附件**: 建议单独处理,不要批量
- **批次间延迟**: 每批间隔 1-2 秒

### 3. 关联字段优化

- **减少嵌套查询**: 使用 get_record_relations API 一次获取
- **批量查询**: 避免 N+1 查询问题
- **缓存关联数据**: 频繁访问的关联数据可缓存
- **控制 showFields**: 只显示必要字段,减少数据量

**详细说明:** 参考 `references/hap-api-usage-guide.md` 第 8 节

---

## 🤖 AI 助手使用指南

当用户需要调用 HAP V3 API 时,AI 助手应该遵循以下原则:

### 1. 自动提取鉴权密钥

**优先级顺序:**

1. **优先从 MCP 配置提取**(推荐)
   - 读取 Cursor 全局设置文件
   - 查找 `hap-mcp-*` 配置
   - 从 URL 中提取 `HAP-Appkey` 和 `HAP-Sign`
   - 如果找到多个配置,询问用户使用哪个应用

2. **用户手动提供**
   - 如果未找到 MCP 配置,提示用户提供 Appkey 和 Sign
   - 或引导用户先配置 MCP

3. **引导配置 MCP**
   - 如果用户有 MCP 配置信息,帮助用户配置到 Cursor
   - 然后从配置中提取密钥

### 2. 配置请求头

提取到密钥后,自动配置请求头:

```javascript
const headers = {
  'Content-Type': 'application/json',
  'HAP-Appkey': extractedAppkey,  // 从 MCP 配置提取
  'HAP-Sign': extractedSign        // 从 MCP 配置提取
};
```

### 3. 处理多个应用

如果用户配置了多个 HAP MCP:

- **明确指定应用名**: 如果用户提到具体应用名,使用对应的配置
- **询问用户**: 如果未指定,列出所有配置的应用,让用户选择
- **默认使用**: 如果只有一个配置,直接使用

### 4. 错误处理

- **配置不存在**: 提示用户先配置 MCP 或手动提供密钥
- **URL 解析失败**: 检查 URL 格式是否正确
- **参数缺失**: 检查 Appkey 和 Sign 是否都存在
- **权限问题**: 如果无法读取配置文件,提示用户检查文件权限

### 5. 实际操作示例

**场景**: 用户说"帮我调用 HAP API 查询数据"

**AI 操作流程**:
1. 读取 Cursor 全局设置文件 `~/Library/Application Support/Cursor/User/settings.json`
2. 查找 `mcpServers` 中的 `hap-mcp-*` 配置
3. 如果找到配置,从 URL 中提取 Appkey 和 Sign
4. 如果找到多个配置,询问用户使用哪个应用
5. 使用提取的密钥配置 API 请求头
6. 执行 API 调用

**场景**: 用户提供了 MCP 配置信息

**AI 操作流程**:
1. 先帮助用户将 MCP 配置添加到 Cursor 全局设置文件
2. 然后从配置中提取 Appkey 和 Sign
3. 使用提取的密钥进行后续 API 调用

---

## 最佳实践

### 1. 初始化阶段

**必做事项:**
1. 查询所有工作表结构
2. 缓存所有选项字段的 key-value 映射
3. 缓存工作表 ID 和字段 ID
4. 建立用户姓名→ID 映射

**示例代码:**
```javascript
// 1. 获取工作表结构
const structure = await getWorksheetStructure(worksheetId);

// 2. 提取选项字段映射
const optionMaps = {};
structure.fields.forEach(field => {
  if (field.type === 'SingleSelect' || field.type === 'MultipleSelect') {
    optionMaps[field.id] = {};
    field.options.forEach(opt => {
      optionMaps[field.id][opt.value] = opt.key;  // value → key
    });
  }
});

// 3. 使用时查找key
const customerTypeKey = optionMaps['customer_type']['成交客户'];
```

### 2. 查询阶段

**建议:**
1. 优先使用字段 ID 而不是别名
2. 选项字段必须用 key,提前转换
3. 数值字段 value 用字符串
4. 关联字段用 belongsto 操作符
5. 合理设置 pageSize(建议 100-500)

### 3. 写入阶段

**检查清单:**
- [ ] 选项字段 value 是数组格式
- [ ] 选项字段传的是 key 不是 value
- [ ] 数值字段传数字类型
- [ ] 关联字段传的是 rowid
- [ ] 成员字段传的是 accountId
- [ ] 附件字段设置了 type 参数

### 4. 错误处理

**常见错误码:**
- `error_code: 1` - 成功
- `error_code: -1` - 失败,查看 error_msg
- `error_code: 4` - 权限不足
- `error_code: 10` - 参数错误

**建议:** 所有 API 调用都要检查 error_code 和 success

**详细说明:** 参考 `references/hap-api-usage-guide.md` 第 9 节

---

## 常用 API 端点速查

| 场景 | API 端点 | 关键参数 |
|-----|---------|---------|
| 创建工作表 | `POST /v3/app/worksheets` | fields |
| 添加字段 | `POST /v3/app/worksheets/{id}` | addFields |
| 创建记录 | `POST /v3/app/worksheets/{id}/rows` | fields |
| 批量创建 | `POST /v3/app/worksheets/{id}/rows/batch` | rows |
| 查询记录 | `POST /v3/app/worksheets/{id}/rows/list` | filter, sorts |
| 更新记录 | `POST /v3/app/worksheets/{id}/rows/{row_id}` | fields |
| 批量更新 | `PUT /v3/app/worksheets/{id}/rows/batch` | rowIds, fields |
| 删除记录 | `DELETE /v3/app/worksheets/{id}/rows/{row_id}` | permanent |
| 批量删除 | `DELETE /v3/app/worksheets/{id}/rows/batch` | rowIds, permanent |
| 透视分析 | `POST /v3/app/worksheets/{id}/rows/pivot` | rows, values |
| 查找用户 | `POST /v3/users/lookup` | name |
| 查找部门 | `POST /v3/departments/lookup` | name |
| 获取地区 | `POST /v3/regions` | search, id |

---

## 参考资源

### 核心文档

- **`references/hap-api-usage-guide.md`** - HAP V3 API 使用规范完整指南
  - 快速开始 - API 使用流程
  - 创建工作表规范
  - 字段类型参数详解
  - 创建/更新记录规范(triggerWorkflow 详解)
  - 查询筛选规范(Filter 对象结构、操作符列表)
  - 数据透视分析规范
  - 关联字段完整指南
  - 常见陷阱与解决方案
  - 性能优化建议
  - 最佳实践总结

### 在线文档

- [API 整体介绍](https://apifox.mingdao.com/7271706m0.md)
- [字段类型对照表](https://apifox.mingdao.com/7271709m0.md)
- [筛选器使用指南](https://apifox.mingdao.com/7271713m0.md)
- [错误码说明](https://apifox.mingdao.com/7271715m0.md)

### 相关技能

- **HAP 前后端项目搭建指南** - 使用 HAP 作为数据库搭建独立网站
- **HAP MCP 使用指南** - 了解如何使用 HAP MCP 进行应用管理
- **HAP 视图插件开发指南** - 开发 HAP 自定义视图插件

---

## 关键概念速查

**字段类型 (type):**
- 基础: `Text`, `Number`, `Date`, `Time`
- 选择: `SingleSelect`, `MultipleSelect`
- 关系: `Relation`, `Collaborator`, `Department`
- 其他: `Attachment`, `Rating`

**筛选操作符 (operator):**
- 比较: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`
- 文本: `contains`, `startswith`, `endswith`
- 范围: `between`, `in`
- 关联: `belongsto`
- 空值: `isempty`, `isnotempty`

**subType 参数:**
- Collaborator: `0`=单选, `1`=多选
- Relation: `1`=单条, `2`=多条
- Time: `1`=时:分, `6`=时:分:秒
- Date: `3`=年月日, `6`=年月日时分秒

---

## 错误排查清单

**筛选无结果:**
- [ ] 选项字段是否用了 key 而不是 value?
- [ ] 数值字段 value 是否用了字符串?
- [ ] 关联字段是否用了 belongsto?
- [ ] Filter 嵌套是否超过 2 层?
- [ ] 字段 ID 是否正确?

**创建/更新失败:**
- [ ] 必填字段是否都提供了?
- [ ] 关联字段的 dataSource 是否存在?
- [ ] 选项字段的 key 是否有效?
- [ ] 成员字段的 accountId 是否有效?
- [ ] 数值字段是否超出范围?

**数据异常:**
- [ ] 附件是否等待了 5-10 秒?
- [ ] 日期精度 subType 是否正确?
- [ ] 关联记录是否已删除?

---

**技能版本**: v2.0  
**最后更新**: 2026-01-11  
**基于**: HAP API V3  
**详细规范**: 参考 `references/hap-api-usage-guide.md`

Install

Requires askill CLI v1.0+

Metadata

LicenseUnknown
Version-
Updated1w ago
Publishergarfield-bb

Tags

apigithubllm