e10-data
v0.1.20
Published
泛微 E10 数据接口统一 CLI(data-assistant 专家配套):登录(login xiaoe-env,环境变量 XiaoE 全局 token 换 ETEAMSID,免浏览器/免 python)/DSL 查询/数据源/文档/词库/关联字段翻译/环境参数配置中心(conf,支持 confGroup 分组)/EB 建模表单权限校验(eb perm-page)/专家包版本管理;ds 取数(list/chart/stat/count)的 appId 由调用方显式传入 --app-id(v0.1.14
Readme
e10-data
泛微 E10 数据接口统一命令行工具(「数据助手」data-assistant 专家配套)。将专家内散落的 HTTP 接口调用收敛为统一的 CLI 命令面。
安装
npm i -g e10-data # 全局安装
e10-data --version # 验证依赖:认证唯一来源 =
weaver-work-cli(不设回退)。加解密全部由e10-login负责,本 CLI 不实现任何加解密(auth 文件由 e10-login 自己的密钥体系加密:1.5.0 起为「每机随机密钥 + OS keychain」,早期版本为固定 seed,只有 e10-login 解得开)。CLI 通过 e10-login 的命令出口取明文凭据,优先级:①e10-login auth --json(推荐的正式契约)→ ②e10-login whoami --json(其 JSON 带cookies时)→ ③e10-login whoami(文本解析,当前实际路径)→ ④ 明文镜像~/.workbuddy/e10-login-cache.md(兜底,命中时打印告警)。请先安装并登录 weaver-e10-login(e10-login oidc)。唯一例外:
e10-data login xiaoe-env在「还没有任何凭据」时也能独立完成登录(用环境变量里的 XiaoE 全局 token 换 ETEAMSID;换 token 本 CLI 自己算,写 profile 仍交e10-login set)。
命令总览
e10-data login xiaoe-env [--domain <url>] 登录:环境变量 XiaoE token 换 ETEAMSID(免浏览器/免 python)
e10-data query <--conn <connId> --model <ebuilder|flow|eteams|attend|hr|document|dw|blog> --schema <数据库> [--table-id <流程ID>] [--debug true|false] --dsl @file.json>
e10-data ds tables|fields|list|chart|stat|count 数据源(业务模块)取数与元数据
e10-data doc count|list 文档查询(documentListCount + documentList)
e10-data noun list --skill <skillKey> 词库查询(可带 --source-type/--source-group/--source-table 三参数)
e10-data field id2name|name2id 关联字段翻译(testRemoteBrowser / complete)
e10-data conf get|batch|batch-file|group|group-file|resolve|resolve-file|add|add-file|update|delete 环境参数配置中心(chatBi config map,替代 config-resolve 脚本 URL 直连;confType 默认按 CONN_/DS_/WF_/API_ 前缀推导,可 --type 显式;confType=api 时支持 confGroup 分组,见下)
e10-data exp status|manifest|commits|file|pull|init|commit|lock|release|rollback 专家包版本管理
e10-data attend statis 考勤假期余额统计 getAttendInfoStatis(hr-attendance 病假/事假等,v0.1.5 新增)通用约定
--json:原样输出接口 JSON(供脚本/Agent 消费);默认人读输出。- 复杂 JSON/中文参数:推荐
@文件承载(如--dsl @q.json、--where @cond.json)。 - ⚠️ 大整数精度(自动处理):E10 的 ID 多为 19 位,超过 JS 安全整数(2^53-1≈9e15)。CLI 解析 JSON 时自动把超范围裸整数转成字符串再发请求/输出(实测后端接受字符串做 =/IN/BETWEEN 数值比较),无需手动加引号,也不误伤字符串正文。
- 认证:加解密由
e10-login负责(本 CLI 不参与)。凭据出口:weaver-work-cli auth export-weaver-env(解析WEAVER_BASE_URL/WEAVER_ETEAMSID/WEAVER_COOKIE,另补一次auth status取userId/tenantKey),已移除 e10-login 回退。命中的出口会记入~/.e10-cli/.e10-data-auth-mode(只存模式名、不存凭据),下次优先复用。环境变量:E10_DATA_AUTH_PROBE=1强制重新探测、E10_DATA_AUTH_MODE=<模式名>手动指定、E10_DATA_QUIET=1抑制告警(告警只走 stderr)。没有任何可用凭据时用e10-data login xiaoe-env登录(见下节)。 - 版本更新:
npm i -g e10-data@latest;查看源上最新npm view e10-data version。
性能:免凭据命令与凭据缓存(v0.1.17 新增)
① 免凭据命令不再取凭据:--version / -v、--help / -h、以及未知命令的用法提示都不需要登录态,现在在取凭据之前直接返回。实测这些路径从 ~2.4s 降到 ~0.2s。
② 直连 e10-login,去掉 shell 中转:过去用 spawnSync(..., { shell: true }) 拉起 e10-login,在 Windows 上会先起一层 cmd.exe——实测该层单独就要约 1.0s(杀软逐进程扫描)。现在改为定位 e10-login 的 JS 入口后用 process.execPath 直接拉起(shell: false)。单次取凭据 ~1.0s → ~0.22s。
若自动定位失败(会打印一行 warn),可用
E10_LOGIN_ENTRY=<e10-login/bin/e10-login.js 绝对路径>显式指定;仍失败则自动退化为 shell 调用(只慢不错)。
③ 凭据进程间 TTL 缓存(默认 300 秒):一个 detached 的持有者进程把凭据只保存在内存里,监听本机命名管道(Windows)/ Unix 域套接字(0600),供后续同用户·同 profile 的调用直接取用,TTL 到期自动退出。不写任何文件、不经过网络。
- 通道名含「用户主目录 + 用户名 + profile」哈希 → 不同用户 / 不同 profile 互不可见;
- 兜底出口(明文镜像)的凭据不写入缓存,避免把可能过期的凭据固化;
- 任何异常(连不上 / 超时 / JSON 损坏 / 已过期 / profile 不符)静默回落到正常取凭据路径。
三项合计:e10-data conf get … 单次调用实测 2.35s → 0.62s(约 3.8 倍)。
相关环境变量:
| 变量 | 作用 |
|---|---|
| E10_DATA_CRED_TTL | 缓存 TTL 秒数,默认 300 |
| E10_DATA_NO_CRED_CACHE=1 | 整体关闭凭据缓存(每次仍直连 weaver-work-cli) |
| E10_DATA_AUTH_PROBE=1 / E10_DATA_AUTH_MODE=… | 存在时绕过缓存,强制重新解析凭据 |
| WEAVER_WORK_CLI_ENTRY | 显式指定 weaver-work-cli 的 JS 入口路径(凭据出口排障用) |
| E10_LOGIN_ENTRY | 显式指定 e10-login 的 JS 入口路径(仅 login xiaoe-env 落 profile 时用) |
⚠️ TTL 采用「先到先得」:若已有一个 TTL=300 的持有者在服务,此时以更短的
E10_DATA_CRED_TTL再调用不会立刻缩短它的寿命(新持有者因通道被占而静默退出)。日常使用无需关注。
用法示例
e10-data query --conn 1144919996804022272 --model dw --schema dw --dsl @q.json
e10-data query --conn 1144919996804022272 --model dw --schema dw --debug true --dsl @q.json # debug 模式:额外打印实际执行 SQL
e10-data ds count --group weaver-project-servicetask --table 715738355537494016
e10-data ds fields --group weaver-formreport-service --table 1307487628041044060
e10-data doc count --name 智能问数
e10-data noun list --skill rd-department
e10-data field id2name --module ebuilder/form --type ebuilder --ids 3194494277170470571 \
--form-param '{"fieldId":"966849910772850766","module":"ebuilderform"}'
e10-data conf get CONN_EC_EDCAPP # 读配置中心单条
e10-data conf resolve '{"connId":"#{CONN_EC_EDCAPP}"}' # 占位符替换为真实值
e10-data conf add CONN_EC_EDCAPP --value 10 --name "说明" --attrs '{"schema":"ec_edcapp"}'
e10-data conf delete CONN_EC_EDCAPP
# confType=api + confGroup 分组(v0.1.9 新增)
e10-data conf group api workflow # 按 类型+分组 批量查全部配置
e10-data conf get GET_WORKFLOW_LIST --type api --group workflow # 单查(组内定位)
e10-data conf add GET_WORKFLOW_LIST --type api --group workflow --value /api/workflow/getList --name 查询流程列表 --attrs '{"request":{"pageNo":"页码"},"response":{"list":"流程列表"}}'
e10-data conf add-file @api-items.json # 批量新增(元素含 confGroup,见下)
e10-data conf update GET_WORKFLOW_LIST --type api --group workflow --value /api/workflow/queryList
e10-data conf delete GET_WORKFLOW_LIST --type api --group workflow
e10-data exp status --expert data-assistant
e10-data exp pull --expert data-assistant --dir <本地专家包目录> [--dry-run] [--force]
e10-data attend statis # 查当前登录用户当月假期余额(病假/事假/年假)
e10-data attend statis --user 6264843388578732287 --begin 2026-09-01 --end 2026-09-30
# 无凭据时先登录(环境变量里的 XiaoE 全局 token 换 ETEAMSID)
XIAOE_USER_TOKEN=<XiaoE token> XIAOE_DOMAIN=<erpa域名> e10-data login xiaoe-env --domain https://www.e-cology.com.cnlogin xiaoe-env 登录(v0.1.16 新增,移植自 e10-login 1.6.4-xiaoe)
e10-data login xiaoe-env [--domain <url>] [--json]:用环境变量 XIAOE_USER_TOKEN(XiaoE 全局 token)+ XIAOE_DOMAIN(erpa 域名)换出 ETEAMSID 并写入 profile,免浏览器、免手动复制 cookie。别名:e10-data xiaoe-env(与 e10-login 的同名命令一致)。
这是唯一不需要已有凭据的命令族(其余命令都要求先有登录态),因此它在 loadAuth() 之前被拦截执行。
| 步骤 | 做什么 | 谁做 |
|---|---|---|
| ① 换 token | POST {$XIAOE_DOMAIN}/spec-apps/api/app/rpachat/skill/extend/eteamId,请求头 authorization: <XIAOE_USER_TOKEN>,body {"domain":"<--domain 或当前 profile 的 baseUrl>"},取回 data.eteamId(code 取 0000/200 为成功) | 本 CLI 原生实现(无 python 依赖) |
| ② 落 profile | e10-login set --eteamsid <id> --base-url <url>:teamsCheck 解析用户信息 + 写加密 auth/config + 切换 active profile | e10-login(auth 文件加密只有它解得开) |
| ③ 自检 | 立刻用取数链路把凭据读回来(loadAuth),读不回就报错退出(不假成功) | 本 CLI |
# Windows cmd
set XIAOE_USER_TOKEN=<token>&& set XIAOE_DOMAIN=<erpa域名>&& e10-data login xiaoe-env --domain https://www.e-cology.com.cn
# bash / git-bash
XIAOE_USER_TOKEN=<token> XIAOE_DOMAIN=<erpa域名> e10-data login xiaoe-env --domain https://www.e-cology.com.cn--domain:目标 e-cology 域名;缺省 = 当前 profile 的config.json.baseUrl(明文,读取不涉及解密)→ 再缺省为默认平台地址https://www.e-cology.com.cn;--json:stdout 只输出结果 JSON(baseUrl/profile/credentialSource/writtenBy/readback),其余信息走 stderr,便于脚本消费;ETEAMSID 一律不回显;- 与原版差异:e10-login 的实现是
spawn python scripts/xiaoe_env.py(需本机 python 3),本 CLI 直接原生发请求,不需要 python;请求形状与 code 判定逐字段对齐。
conf 配置中心与 confGroup 分组(v0.1.9 新增)
conf 系列对接 chatBi config map 接口,confGroup 是可选的二级分组维度:后端在 confType=api 时按 confType + confGroup + confKey 定位配置(如 api/workflow/GET_WORKFLOW_LIST),用于把同类 API 定义归档到同一分组。
下发规则(重要):只有 confType 为 api(或显式传了 --group)时,CLI 才会在请求体/查询串里带上 confGroup;其他 confType 一律不带该字段,避免污染既有配置类型。
| 操作 | 命令 | 对应接口 |
|---|---|---|
| 新增(批量,可含分组) | conf add <key> --value v [--type api] [--group g] / conf add-file @items.json | POST /api/dw/newetl/chatBi/batchAddChatBiConfigMap |
| 单查 | conf get <key> [--type api] [--group g] | GET /api/dw/newetl/chatBi/getChatBiConfigMap?confType=&confGroup=&confKey= |
| 批量查(按 key) | conf batch <k1> <k2> ... / conf batch-file @items.json | POST /api/dw/newetl/chatBi/batchGetChatBiConfigMap |
| 批量查(按类型+分组) | conf group <confType> <confGroup> [--key k] / conf group-file @items.json | POST /api/dw/newetl/chatBi/batchGetChatBiConfigMapByTypeAndGroup |
| 更新 | conf update <key> [--value v] [--name n] [--attrs a] [--group g] | POST /api/dw/newetl/chatBi/updateChatBiConfigMap |
| 删除 | conf delete <key> [--type api] [--group g] | DELETE /api/dw/newetl/chatBi/deleteChatBiConfigMap?confType=&confGroup=&confKey= |
批量新增文件 api-items.json(confType=api 时元素带 confGroup):
[
{
"confType": "api",
"confGroup": "workflow",
"confKey": "GET_WORKFLOW_LIST",
"confValue": "/api/workflow/getList",
"confName": "查询流程列表",
"confAttrs": "{\"request\":{\"pageNo\":\"页码\",\"pageSize\":\"每页数量\"},\"response\":{\"list\":\"流程列表\"}}"
},
{
"confType": "api",
"confGroup": "workflow",
"confKey": "GET_WORKFLOW_DETAIL",
"confValue": "/api/workflow/getDetail",
"confName": "查询流程详情",
"confAttrs": "{\"request\":{\"id\":\"流程ID\"},\"response\":{\"id\":\"流程ID\",\"name\":\"流程名称\"}}"
}
]e10-data conf add-file @api-items.json # 批量新增(逐条判重:同 组+键 已存在则跳过)
e10-data conf group api workflow # 取回 workflow 分组下全部 API 配置
e10-data conf group-file @groups.json # 多分组一次取回,@groups.json = [{"confType":"api","confGroup":"workflow"}]
e10-data conf update GET_WORKFLOW_LIST --type api --group workflow --value /api/workflow/queryList
e10-data conf delete GET_WORKFLOW_LIST --type api --group workflow补充说明:
confKey前缀推导 confType:CONN_→conn、DS_→ds、WF_→wf、API_→api;其余类型用--type显式指定(--type与--group可同时使用)。- 同一
confKey可存在于多个confGroup;conf batch/batch-file的返回映射在带分组时以组|键为键,不会互相覆盖。 --json输出:conf group返回配置数组(带--key时返回单条),conf batch返回映射对象。
ds appId:由调用方显式传入(v0.1.14 变更,自动解析已移除)
ChatBI 数据源取数接口(getListDatas / getChartDatas / getStatDatas / getCountData)对**部分 EB 应用(独立部署)**的数据集,必须在 queryDto 中携带 appId,否则后端一律返回 code=500 请求失败(实测:小餐厅应用 840360791696547845 名下 4 张表不传全 500、传即 200;低代码大赛等应用不传也正常,显式传其真实 appId 同样返回 200)。
⚠️ v0.1.14 行为变更(breaking):v0.1.13 的「自动解析 appId」已整体移除。原因:
chat_bi_eb_config_map是权限表——它的行代表「谁有权限查哪张表」,app_id只是该行的附带字段。appId 应是权限校验那一次查询的产物,不应由 CLI 另开一条查询去反查(否则等于把权限表当普通字典使用,且 appId 来源对调用者不可见)。同步移除的还有ebdf_obj兜底来源(该表无权限语义)。
正确姿势:先权限校验(顺带取到 appId),再显式传入取数。
① 调用方(技能 / Agent)先做权限校验,一条 DSL 同时得到「有没有权限」与「要带的 appId」:
# ① 权限校验(DSL,dw 库 / #{CONN_DW}):obj_id 命中 → 有权限;未命中 → 无权限,直接返回提示、不取数
# SELECT obj_id, app_id FROM chat_bi_eb_config_map
# WHERE delete_type=0 AND tenant_key=<租户> AND enabled=1 AND (all_scop=1 OR target_id=<当前人员ID>)
# ② 取数:EB 建模表单必须带 --app-id(值 = ① 中该行的 app_id)
e10-data ds count --group weaver-ebuilder-form-service --table 840360795890851856 --app-id 840360791696547845
e10-data ds fields --group weaver-ebuilder-form-service --table 840360795890851856 --app-id 840360791696547845
# 非 EB 数据集:无需 appId,照常调用
e10-data ds count --group weaver-project-servicetask --table 715738355537494016
# 查看某张表的 appId:ds tables 输出含 appId 列(服务端返回字段,仅展示用,与取数参数无关)
e10-data ds tables --group weaver-ebuilder-form-service --name 低代码大赛
- 仅 EB 建模表单分组(
weaver-ebuilder-form-service) 需要 appId;其他数据集传了也无害。- 不传时 CLI 不做拦截(即使 EB 分组):按原样发送,由后端报错(与后端行为一致)。
--app-id auto/--no-app-id自 v0.1.14 起为空操作(等同不传),仅为兼容旧脚本保留参数位。- 同一 appId 覆盖同一应用下的多张表(实测小餐厅 4 张表共用
840360791696547845),按obj_id从权限表取到即可直接复用。- 权限校验查询走
#{CONN_DW}(占位符由 CLI 向配置中心解析);该表需在 DSL 表授权白名单内。
ds --where 过滤条件(v0.1.8 起支持树形 OR)
e10-data ds list|chart|stat|count --where 接收条件数组或完整条件树,均可递归嵌套表达 AND/OR:
# ① 数组 = AND 根(旧写法,行为不变):满足全部条件的记录
e10-data ds count --group <gid> --table <tid> \
--where '[{"fieldId":"fieldA","compareType":"range","conditionValue":"2026-09~2026-10"},{"fieldId":"fieldB","compareType":"eq","conditionValue":"1"}]'
# ② 对象 = 完整条件树:relationship "0"=OR、"1"=AND(缺省 AND),conditionList 内可再嵌套条件组
e10-data ds count --group <gid> --table <tid> \
--where '{"relationship":"0","conditionList":[{"fieldId":"fieldA","compareType":"range","conditionValue":"2026-09~2026-10"},{"fieldId":"fieldB","compareType":"range","conditionValue":"2026-09~2026-10"}]}'
# ③ 数组元素内嵌条件组 → 复杂组合,如 (A AND B) OR (C AND D)
e10-data ds list --group <gid> --table <tid> --fields a,b \
--where @cond.json # 内容见下// cond.json —— 组合条件示例
[
{ "relationship": "1", "conditionList": [
{ "fieldId": "A", "compareType": "eq", "conditionValue": "x" },
{ "fieldId": "B", "compareType": "eq", "conditionValue": "y" } ] },
{ "relationship": "0", "conditionList": [
{ "fieldId": "C", "compareType": "eq", "conditionValue": "m" },
{ "fieldId": "D", "compareType": "eq", "conditionValue": "n" } ] }
]要点:
- 叶子字段键:
fieldId与conditionId均可(fieldId 优先),旧树形conditionId写法兼容; - relationship:
"0"/0/false= OR,其余 = AND;子节点关系作用于其自身conditionList; - 数组顶层恒为 AND 根,需要整体 OR 请用对象形态
{"relationship":"0","conditionList":[...]}; - 叶子缺少字段会直接报错(v0.1.8 起,不再静默产生空条件导致误返回全表);
- 其余条件属性(conditionType/compareType/conditionValue/objId/mainField/ignoreCaseMark 等)照旧透传。
exp pull 智能拉取(v0.1.4 新增,防本地修改被覆盖)exp pull 不再盲目覆盖。CLI 在专家包本地目录维护基线文件 .sync-state.json(记录上次同步的 commitId/headRevision 与每文件 sha256),拉取时逐文件三方对比:
| 场景 | 判定 | 处理 |
|---|---|---|
| 仅远端改(本地未动) | 本地 sha == 基线 sha ≠ 远端 sha | 直接下载覆盖(安全) |
| 仅本地改(远端未动) | 本地 sha ≠ 基线 sha == 远端 sha | 保留本地,不覆盖 |
| 双方都改 / 无基线可判 | 本地、基线、远端互不相同 | 先备份本地副本到 <专家包目录>.pull-backup-<时间戳>/,再下载覆盖 |
| 本地缺失 | manifest 有、本地无 | 直接下载(新增/恢复) |
- 拉取成功后将
.sync-state.json刷新到新 head,后续判定持续准确; --force:一律以远端覆盖(放弃本地修改,不备份);--dry-run:只预览决策,不写盘不下载;.sync-state.json为本地同步元文件,永不随包提交(walkDir/collectPackage已排除);exp commit成功后也会自动刷新该基线。
attend statis 考勤假期余额(v0.1.5 新增)
封装 E10 考勤 REST 接口 POST /api/attend/web/attendInfoV2/getAttendInfoStatis(hr-attendance 场景六:病假/事假/年假余额统计,替代原手工 curl)。认证/绕代理由 CLI 进程内自动完成(权威源 ~/.e10-cli/profiles/<active>/auth)。
e10-data attend statis [--user <人员ID>] [--begin 2026-09-01] [--end 2026-09-30]--user:目标人员 ID;缺省 = 当前登录用户(查他人前需先 HRM 下属校验,见 hr-attendance Skill);--begin/--end:统计月份范围,缺省 = 当前月 1 日 ~ 月末(接口按整月统计,时间范围不影响假期余额口径);--json:原样输出接口 JSON(含data.attendStatis出勤统计 /data.attendSummary汇总 /data.leaveInfo请假 /data.outAttend外出 /data.vacationBalanceList假期余额);- 默认人读输出:仅列出
data.vacationBalanceList(按 title 区分假期类型)——带薪病假100584850000000003、带薪事假100584850000000010含lastRemaining(历年可请)/remaining(今年可请)/total(总计可请) 三项。
