添加技能
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
# 本地敏感配置
|
||||
.yierp/config.json
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyo
|
||||
*.pyd
|
||||
.venv/
|
||||
venv/
|
||||
|
||||
# 通用
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -0,0 +1,83 @@
|
||||
# YIERP CLI 技能说明
|
||||
|
||||
这是一个面向 YIERP(基于 ERPNext v16)的数据操作脚本包,适合通过配置 URL、apikey 和 ApiSecret 来执行常见的数据查询与写入操作。
|
||||
|
||||
## 目录说明
|
||||
|
||||
- `SKILL.md`:技能说明,适合作为 AI/脚本上下文。
|
||||
- `tools/yierp_cli.py`:YIERP CLI 脚本。
|
||||
- `config.example.json`:示例配置文件。
|
||||
- `requirements.txt`:Python 依赖。
|
||||
|
||||
## 快速开始
|
||||
|
||||
1. 安装依赖:
|
||||
|
||||
```bash
|
||||
python -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. 复制示例配置:
|
||||
|
||||
```bash
|
||||
copy config.example.json .yierp\config.json
|
||||
```
|
||||
|
||||
3. 编辑 `.yierp/config.json`,填入真实参数:
|
||||
|
||||
```json
|
||||
{
|
||||
"url": "https://yierp.example.com",
|
||||
"apikey": "你的_api_key",
|
||||
"ApiSecret": "你的_api_secret",
|
||||
"timeout": 30,
|
||||
"verify_ssl": true
|
||||
}
|
||||
```
|
||||
|
||||
4. 运行命令:
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py whoami --config .yierp/config.json
|
||||
python tools/yierp_cli.py list --doctype ToDo --config .yierp/config.json --limit 10
|
||||
python tools/yierp_cli.py create --doctype ToDo --config .yierp/config.json --data '{"description":"测试任务","status":"Open"}'
|
||||
```
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
# 连接检测
|
||||
python tools/yierp_cli.py whoami
|
||||
|
||||
# 查询列表
|
||||
python tools/yierp_cli.py list --doctype ToDo --filters '{"status":"Open"}' --limit 20
|
||||
|
||||
# 获取单条记录
|
||||
python tools/yierp_cli.py get --doctype ToDo --name "TODO-00001"
|
||||
|
||||
# 创建记录
|
||||
python tools/yierp_cli.py create --doctype ToDo --data '{"description":"新任务","status":"Open"}'
|
||||
|
||||
# 更新记录
|
||||
python tools/yierp_cli.py update --doctype ToDo --name "TODO-00001" --data '{"status":"Closed"}'
|
||||
|
||||
# 删除记录
|
||||
python tools/yierp_cli.py delete --doctype ToDo --name "TODO-00001" --yes
|
||||
|
||||
# 调用自定义方法
|
||||
python tools/yierp_cli.py method --method "your_app.api.test" --args '{"message":"hello"}'
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 对于删除、更新和批量修改类操作,请先确认 DocType、名称和修改内容。
|
||||
- `ApiSecret` 是敏感信息,请勿提交到代码仓库或日志中。
|
||||
- 生产环境建议使用环境变量覆盖配置:
|
||||
|
||||
```bash
|
||||
set YIERP_URL=https://yierp.example.com
|
||||
set YIERP_APIKEY=你的_api_key
|
||||
set YIERP_APISECRET=你的_api_secret
|
||||
```
|
||||
|
||||
- 如果 YIERP 站点使用自签名证书或内网 HTTPS,请适当调整 `verify_ssl`。
|
||||
@@ -0,0 +1,164 @@
|
||||
---
|
||||
name: yierp-cli
|
||||
description: 适用于 YIERP(源自 ERPNext v16)的数据访问与管理技能,支持通过配置 url、apikey、ApiSecret 完成查询、创建、更新、删除和自定义方法调用。
|
||||
---
|
||||
|
||||
# YIERP CLI 数据操作技能
|
||||
|
||||
这个技能用于访问 YIERP 系统中的业务数据与文档资源。YIERP 继承 ERPNext v16 的 Frappe / REST API 设计,因此可以使用标准的 HTTP API 方式进行 DocType 数据访问、文档操作和后端方法调用。
|
||||
|
||||
## 适用目标
|
||||
|
||||
- 通过配置 `url`、`apikey`、`ApiSecret` 建立认证
|
||||
- 支持 `list`、`get`、`create`、`update`、`delete`、`method`、`whoami` 等操作
|
||||
- 适合脚本自动化、批量同步、业务查询、报表提取和业务集成
|
||||
- 所有说明、注释、提示和输出都使用简体中文
|
||||
|
||||
## 配置方式
|
||||
|
||||
### 1. 配置文件方式
|
||||
|
||||
建议在项目中创建 `.yierp/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"url": "https://yierp.example.com",
|
||||
"apikey": "你的_api_key",
|
||||
"ApiSecret": "你的_api_secret",
|
||||
"timeout": 30,
|
||||
"verify_ssl": true
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 环境变量方式
|
||||
|
||||
```bash
|
||||
set YIERP_URL=https://yierp.example.com
|
||||
set YIERP_APIKEY=你的_api_key
|
||||
set YIERP_APISECRET=你的_api_secret
|
||||
```
|
||||
|
||||
### 3. 命令行参数方式
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py list --doctype ToDo --url https://yierp.example.com --apikey xxx --apisecret yyy
|
||||
```
|
||||
|
||||
## 关键命令
|
||||
|
||||
### 1. 检查当前登录用户
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py whoami --config .yierp/config.json
|
||||
```
|
||||
|
||||
### 2. 查询列表
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py list --doctype ToDo --config .yierp/config.json --filters '{"status":"Open"}' --limit 20
|
||||
```
|
||||
|
||||
### 3. 获取单条记录
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py get --doctype ToDo --name "TODO-00001" --config .yierp/config.json
|
||||
```
|
||||
|
||||
### 4. 创建记录
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py create --doctype ToDo --config .yierp/config.json --data '{"description":"测试任务","status":"Open"}'
|
||||
```
|
||||
|
||||
### 5. 更新记录
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py update --doctype ToDo --name "TODO-00001" --config .yierp/config.json --data '{"status":"Closed"}'
|
||||
```
|
||||
|
||||
### 6. 删除记录
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py delete --doctype ToDo --name "TODO-00001" --config .yierp/config.json --yes
|
||||
```
|
||||
|
||||
### 7. 调用自定义后端方法
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py method --method your_app.api.test --config .yierp/config.json --args '{"message":"hello"}'
|
||||
```
|
||||
|
||||
### 8. 查看当前配置摘要
|
||||
|
||||
```bash
|
||||
python tools/yierp_cli.py config --config .yierp/config.json
|
||||
```
|
||||
|
||||
## 认证方式
|
||||
|
||||
YIERP 使用 Frappe / ERPNext 风格的 token 认证:
|
||||
|
||||
```text
|
||||
Authorization: token {apikey}:{ApiSecret}
|
||||
```
|
||||
|
||||
因此,在访问 API 时,必须提供:
|
||||
|
||||
- `url`:站点地址,例如 `https://yierp.example.com`
|
||||
- `apikey`:API 密钥
|
||||
- `ApiSecret`:对应的 API Secret
|
||||
|
||||
## 数据操作能力
|
||||
|
||||
### 查询类
|
||||
|
||||
- `list`:根据 DocType 查询多条记录
|
||||
- `get`:获取单个文档详情
|
||||
- `whoami`:验证当前认证用户
|
||||
|
||||
### 写入类
|
||||
|
||||
- `create`:新增数据记录
|
||||
- `update`:修改已有记录
|
||||
- `delete`:删除记录
|
||||
|
||||
### 业务集成类
|
||||
|
||||
- `method`:调用后端方法或自定义逻辑
|
||||
- `config`:查看当前配置状态
|
||||
|
||||
## 安全要求
|
||||
|
||||
1. 更新或删除前必须确认 DocType、记录名称和修改字段。
|
||||
2. `ApiSecret` 为敏感信息,必须仅保存在本地配置中,不得写入日志、截图或仓库。
|
||||
3. 若 YIERP 使用自签名证书,需关闭 SSL 校验或配置 `verify_ssl: false`。
|
||||
4. 最小权限原则:优先用 `list` 与 `get` 做验证,再执行写入操作。
|
||||
|
||||
## 失败处理
|
||||
|
||||
遇到失败时,优先检查以下问题:
|
||||
|
||||
- URL 是否正确,站点是否可达
|
||||
- `apikey` 与 `ApiSecret` 是否匹配
|
||||
- DocType 名称是否存在
|
||||
- 请求体 JSON 是否符合规范
|
||||
- API 路径是否正确,是否为 `api/resource` 或 `api/method`
|
||||
- SSL 证书错误是否需要使用 `--no-verify-ssl`
|
||||
|
||||
## 适用场景
|
||||
|
||||
- 客户、供应商、订单、发票、库存、出入库等数据查询
|
||||
- 批量报表导出与任务调度
|
||||
- ERP 系统与 CRM、WMS、MES 等系统集成
|
||||
- 调用 YIERP 自定义 Python 方法实现复杂业务逻辑
|
||||
|
||||
## 说明
|
||||
|
||||
本技能是为 YIERP(源自 ERPNext v16 的定制 ERP 系统)设计的通用接口封装。使用时应优先遵循:
|
||||
|
||||
- 站点配置优先:`url` 为核心入口
|
||||
- 凭证配置优先:`apikey` 与 `ApiSecret` 为认证关键
|
||||
- 最小动作原则:先查询再写入
|
||||
- 安全确认原则:删除与更新必须确认目标后再执行
|
||||
|
||||
如果用户没有明确指定站点,默认使用配置文件中的 `url`。如果用户要求执行数据操作,请优先采用本技能提供的 CLI 脚本执行。
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
exec python "$ROOT/tools/yierp_cli.py" "$@"
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$repoRoot = (Resolve-Path (Join-Path $scriptDir "..")).Path
|
||||
|
||||
$pythonCmd = Get-Command python -ErrorAction SilentlyContinue
|
||||
if (-not $pythonCmd) {
|
||||
Write-Error "未找到 python 命令,请先安装 Python 3.9+。"
|
||||
exit 1
|
||||
}
|
||||
|
||||
& python (Join-Path $repoRoot "tools\yierp_cli.py") @args
|
||||
exit $LASTEXITCODE
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"url": "https://yierp.example.com",
|
||||
"apikey": "你的_api_key",
|
||||
"ApiSecret": "你的_api_secret",
|
||||
"timeout": 30,
|
||||
"verify_ssl": true
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
requests>=2.31.0
|
||||
@@ -0,0 +1 @@
|
||||
"""YIERP 统一工具包。"""
|
||||
@@ -0,0 +1,337 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""YIERP CLI:通过 URL、apikey 和 ApiSecret 访问 YIERP 数据接口。
|
||||
|
||||
本脚本适配 ERPNext / Frappe 风格的 REST API,适用于 YIERP(源自 ERPNext v16)。
|
||||
支持的核心能力包括:
|
||||
- 查询列表
|
||||
- 获取单条记录
|
||||
- 创建文档
|
||||
- 更新文档
|
||||
- 删除文档
|
||||
- 调用自定义方法
|
||||
- 连接检测
|
||||
|
||||
使用方法:
|
||||
python tools/yierp_cli.py --help
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class YIERPConfigError(RuntimeError):
|
||||
"""配置错误。"""
|
||||
|
||||
|
||||
class YIERPRequestError(RuntimeError):
|
||||
"""API 请求错误。"""
|
||||
|
||||
|
||||
def _safe_json_loads(raw: Optional[str], label: str) -> Any:
|
||||
"""安全解析 JSON 字符串。"""
|
||||
if raw is None:
|
||||
return None
|
||||
try:
|
||||
return json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise ValueError(f"{label} 不是合法的 JSON: {raw}") from exc
|
||||
|
||||
|
||||
def _mask_value(value: Optional[str]) -> str:
|
||||
"""掩码保护敏感字段。"""
|
||||
if value is None:
|
||||
return "未配置"
|
||||
if len(value) <= 6:
|
||||
return "******"
|
||||
return f"{value[:2]}******{value[-2:]}"
|
||||
|
||||
|
||||
def _load_json_file(file_path: str) -> Dict[str, Any]:
|
||||
"""读取 JSON 配置文件。"""
|
||||
path = Path(file_path)
|
||||
if not path.exists():
|
||||
return {}
|
||||
try:
|
||||
with path.open("r", encoding="utf-8") as handle:
|
||||
data = json.load(handle)
|
||||
if isinstance(data, dict):
|
||||
return data
|
||||
raise YIERPConfigError(f"配置文件不是有效的 JSON 对象:{file_path}")
|
||||
except json.JSONDecodeError as exc:
|
||||
raise YIERPConfigError(f"配置文件 JSON 格式错误:{file_path}") from exc
|
||||
|
||||
|
||||
def resolve_config(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""按优先级解析配置:命令行参数 > 环境变量 > 配置文件。"""
|
||||
config_path = args.config or os.getenv("YIERP_CONFIG_PATH", ".yierp/config.json")
|
||||
config_data: Dict[str, Any] = _load_json_file(config_path)
|
||||
|
||||
data: Dict[str, Any] = dict(config_data)
|
||||
|
||||
data["url"] = args.url or os.getenv("YIERP_URL") or data.get("url")
|
||||
data["apikey"] = (
|
||||
args.apikey
|
||||
or os.getenv("YIERP_APIKEY")
|
||||
or data.get("apikey")
|
||||
or data.get("api_key")
|
||||
or data.get("apiKey")
|
||||
)
|
||||
data["ApiSecret"] = (
|
||||
args.apisecret
|
||||
or os.getenv("YIERP_APISECRET")
|
||||
or data.get("ApiSecret")
|
||||
or data.get("api_secret")
|
||||
or data.get("apiSecret")
|
||||
)
|
||||
data["timeout"] = args.timeout or data.get("timeout", 30)
|
||||
data["verify_ssl"] = data.get("verify_ssl", True)
|
||||
|
||||
if args.no_verify_ssl:
|
||||
data["verify_ssl"] = False
|
||||
|
||||
if not data.get("url"):
|
||||
raise YIERPConfigError("缺少配置:URL 未设置。请配置 url 或设置 YIERP_URL。")
|
||||
if not data.get("apikey"):
|
||||
raise YIERPConfigError("缺少配置:apikey 未设置。请配置 apikey 或设置 YIERP_APIKEY。")
|
||||
if not data.get("ApiSecret"):
|
||||
raise YIERPConfigError("缺少配置:ApiSecret 未设置。请配置 ApiSecret 或设置 YIERP_APISECRET。")
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def ensure_headers(config: Dict[str, Any]) -> Dict[str, str]:
|
||||
"""构造 Frappe / ERPNext 的认证头。"""
|
||||
auth_value = f"token {config['apikey']}:{config['ApiSecret']}"
|
||||
return {
|
||||
"Authorization": auth_value,
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
|
||||
def request_json(
|
||||
config: Dict[str, Any],
|
||||
method: str,
|
||||
path: str,
|
||||
params: Optional[Dict[str, Any]] = None,
|
||||
payload: Optional[Dict[str, Any]] = None,
|
||||
) -> Any:
|
||||
"""统一请求 YIERP REST API。"""
|
||||
url = f"{config['url'].rstrip('/')}{path}"
|
||||
headers = ensure_headers(config)
|
||||
|
||||
try:
|
||||
response = requests.request(
|
||||
method=method.upper(),
|
||||
url=url,
|
||||
headers=headers,
|
||||
params=params,
|
||||
json=payload,
|
||||
timeout=config.get("timeout", 30),
|
||||
verify=config.get("verify_ssl", True),
|
||||
)
|
||||
except requests.RequestException as exc:
|
||||
raise YIERPRequestError(f"请求失败:{exc}") from exc
|
||||
|
||||
text = response.text.strip()
|
||||
try:
|
||||
payload_json = response.json() if text else {}
|
||||
except ValueError:
|
||||
payload_json = {"raw": text}
|
||||
|
||||
if response.status_code >= 400:
|
||||
message = payload_json.get("exc") or payload_json.get("exception") or payload_json.get("message") or text or "未知错误"
|
||||
raise YIERPRequestError(f"HTTP {response.status_code}:{message}")
|
||||
|
||||
return payload_json
|
||||
|
||||
|
||||
def parse_json_argument(value: Optional[str], label: str) -> Optional[Any]:
|
||||
"""将命令行 JSON 字符串解析为 Python 对象。"""
|
||||
if value is None:
|
||||
return None
|
||||
return _safe_json_loads(value, label)
|
||||
|
||||
|
||||
def build_list_params(filters: Optional[Any], fields: Optional[Any], limit: int, start: int, order_by: Optional[str]) -> Dict[str, Any]:
|
||||
"""构造列表查询参数。"""
|
||||
params: Dict[str, Any] = {}
|
||||
if filters is not None:
|
||||
params["filters"] = json.dumps(filters)
|
||||
if fields is not None:
|
||||
params["fields"] = json.dumps(fields)
|
||||
if order_by:
|
||||
params["order_by"] = order_by
|
||||
if limit is not None:
|
||||
params["limit_page_length"] = limit
|
||||
if start is not None:
|
||||
params["limit_start"] = start
|
||||
return params
|
||||
|
||||
|
||||
def cmd_whoami(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""检查当前登录用户。"""
|
||||
config = resolve_config(args)
|
||||
return request_json(config, "GET", "/api/method/frappe.auth.get_logged_user")
|
||||
|
||||
|
||||
def cmd_list(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""查询文档列表。"""
|
||||
config = resolve_config(args)
|
||||
doctype = args.doctype
|
||||
filters = parse_json_argument(args.filters, "filters")
|
||||
fields = parse_json_argument(args.fields, "fields")
|
||||
params = build_list_params(filters, fields, args.limit, args.start, args.order_by)
|
||||
result = request_json(config, "GET", f"/api/resource/{doctype}", params=params)
|
||||
return result
|
||||
|
||||
|
||||
def cmd_get(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""获取单条文档。"""
|
||||
config = resolve_config(args)
|
||||
doctype = args.doctype
|
||||
name = args.name
|
||||
return request_json(config, "GET", f"/api/resource/{doctype}/{name}")
|
||||
|
||||
|
||||
def cmd_create(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""创建单条文档。"""
|
||||
config = resolve_config(args)
|
||||
doctype = args.doctype
|
||||
payload = parse_json_argument(args.data, "data")
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError("创建数据必须是 JSON 对象。")
|
||||
return request_json(config, "POST", f"/api/resource/{doctype}", payload=payload)
|
||||
|
||||
|
||||
def cmd_update(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""更新单条文档。"""
|
||||
config = resolve_config(args)
|
||||
doctype = args.doctype
|
||||
name = args.name
|
||||
payload = parse_json_argument(args.data, "data")
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError("更新数据必须是 JSON 对象。")
|
||||
return request_json(config, "PUT", f"/api/resource/{doctype}/{name}", payload=payload)
|
||||
|
||||
|
||||
def cmd_delete(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""删除单条文档。"""
|
||||
config = resolve_config(args)
|
||||
doctype = args.doctype
|
||||
name = args.name
|
||||
if not args.yes:
|
||||
raise YIERPRequestError("删除操作需要显式添加 --yes 参数确认。")
|
||||
return request_json(config, "DELETE", f"/api/resource/{doctype}/{name}")
|
||||
|
||||
|
||||
def cmd_method(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""调用自定义的挂钩方法或后端方法。"""
|
||||
config = resolve_config(args)
|
||||
method_name = args.method
|
||||
payload = parse_json_argument(args.args, "args")
|
||||
if payload is None:
|
||||
payload = {}
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError("方法参数必须是 JSON 对象。")
|
||||
return request_json(config, "POST", f"/api/method/{method_name}", payload=payload)
|
||||
|
||||
|
||||
def cmd_config_show(args: argparse.Namespace) -> Dict[str, Any]:
|
||||
"""显示当前配置摘要,隐藏敏感字段。"""
|
||||
config = resolve_config(args)
|
||||
return {
|
||||
"url": config.get("url"),
|
||||
"apikey": _mask_value(config.get("apikey")),
|
||||
"ApiSecret": _mask_value(config.get("ApiSecret")),
|
||||
"timeout": config.get("timeout", 30),
|
||||
"verify_ssl": config.get("verify_ssl", True),
|
||||
}
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
"""构建命令行解释器。"""
|
||||
parser = argparse.ArgumentParser(description="YIERP CLI:基于 ERPNext v16 REST API 的数据操作工具", add_help=True)
|
||||
parser.add_argument("--config", default=None, help="配置文件路径,默认 .yierp/config.json")
|
||||
parser.add_argument("--url", default=None, help="YIERP 站点地址,例如 https://yierp.example.com")
|
||||
parser.add_argument("--apikey", default=None, help="YIERP API Key")
|
||||
parser.add_argument("--apisecret", default=None, help="YIERP ApiSecret")
|
||||
parser.add_argument("--timeout", type=int, default=None, help="请求超时时间,单位秒")
|
||||
parser.add_argument("--no-verify-ssl", action="store_true", help="跳过 SSL 证书校验,适用于自签名证书场景")
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
whoami_parser = subparsers.add_parser("whoami", help="查看当前登录用户")
|
||||
whoami_parser.set_defaults(func=cmd_whoami)
|
||||
|
||||
config_parser = subparsers.add_parser("config", help="显示当前配置摘要")
|
||||
config_parser.set_defaults(func=cmd_config_show)
|
||||
|
||||
list_parser = subparsers.add_parser("list", help="查询数据列表")
|
||||
list_parser.add_argument("--doctype", required=True, help="DocType,例如 ToDo、Sales Invoice、Customer")
|
||||
list_parser.add_argument("--filters", default=None, help="筛选条件,JSON 字符串,例如 '{\"status\":\"Open\"}'")
|
||||
list_parser.add_argument("--fields", default=None, help="查询字段,JSON 数组,例如 '[\"name\",\"status\"]'")
|
||||
list_parser.add_argument("--limit", type=int, default=20, help="返回条数上限")
|
||||
list_parser.add_argument("--start", type=int, default=0, help="分页起始位置")
|
||||
list_parser.add_argument("--order-by", default=None, help="排序字段,例如 name desc")
|
||||
list_parser.set_defaults(func=cmd_list)
|
||||
|
||||
get_parser = subparsers.add_parser("get", help="获取单条记录")
|
||||
get_parser.add_argument("--doctype", required=True, help="DocType")
|
||||
get_parser.add_argument("--name", required=True, help="文档名称或主键值")
|
||||
get_parser.set_defaults(func=cmd_get)
|
||||
|
||||
create_parser = subparsers.add_parser("create", help="创建单条文档")
|
||||
create_parser.add_argument("--doctype", required=True, help="DocType")
|
||||
create_parser.add_argument("--data", required=True, help="创建数据,JSON 对象,例如 '{\"description\":\"新任务\"}'")
|
||||
create_parser.set_defaults(func=cmd_create)
|
||||
|
||||
update_parser = subparsers.add_parser("update", help="更新单条文档")
|
||||
update_parser.add_argument("--doctype", required=True, help="DocType")
|
||||
update_parser.add_argument("--name", required=True, help="文档名称或主键值")
|
||||
update_parser.add_argument("--data", required=True, help="更新数据,JSON 对象,例如 '{\"status\":\"Closed\"}'")
|
||||
update_parser.set_defaults(func=cmd_update)
|
||||
|
||||
delete_parser = subparsers.add_parser("delete", help="删除单条文档")
|
||||
delete_parser.add_argument("--doctype", required=True, help="DocType")
|
||||
delete_parser.add_argument("--name", required=True, help="文档名称或主键值")
|
||||
delete_parser.add_argument("--yes", action="store_true", help="确认执行删除操作")
|
||||
delete_parser.set_defaults(func=cmd_delete)
|
||||
|
||||
method_parser = subparsers.add_parser("method", help="调用后端方法")
|
||||
method_parser.add_argument("--method", required=True, help="方法路径,例如 your_app.api.test")
|
||||
method_parser.add_argument("--args", default=None, help="方法参数,JSON 对象,例如 '{\"message\":\"hello\"}'")
|
||||
method_parser.set_defaults(func=cmd_method)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""主函数入口。"""
|
||||
parser = build_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
result = args.func(args)
|
||||
except (YIERPConfigError, YIERPRequestError, ValueError) as exc:
|
||||
print(f"错误:{exc}", file=sys.stderr)
|
||||
return 1
|
||||
except Exception as exc: # pragma: no cover
|
||||
print(f"未处理错误:{exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user