QuickForm CLI
供命令行、扣子编程、OpenClaw 等工具自动化创建与查看数据任务,无需打开网页。
0. 官方命令行工具
通过 PyPI 安装官方 qf 命令行工具:
python3 -m pip install --upgrade quickform-cli
qf --version
qf login
qf task list
qf task add "课堂签到表" "本周签到"
qf task show <apiid>
qf task export <apiid> task.zip --include-data
qf task upload <apiid> ./index.html
qf submit <apiid> '{"name":"张三"}'
qf data <apiid>
请仅从 PyPI 的 quickform-cli 项目安装,不要使用来源不明的同名包或二进制文件。拥有项目源码访问权限的开发者仍可在仓库根目录执行 python3 -m pip install . 进行开发安装。
首次运行 qf task … 等需要账号权限的命令会进入交互式认证;可选择「用户名 + 密码」或「用户名 + QF 授权码」。也可用 qf login -u <用户名> -a <QF授权码> 进行非交互登录。凭据仅保存到当前用户的 ~/.config/quickform/config.json,文件权限为仅当前用户可读写。推荐使用可在个人中心随时吊销的 QF 授权码。运行 qf logout 可删除本机凭据。
全局选项:qf --base-url https://your.quickform.instance … 可临时指定自建站点;qf --version 显示版本。qf submit、qf brief 和 qf data 调用公开数据接口,不读取本地登录凭据,但仍受任务的读写开关限制。
1. 基础信息
- Base URL:
https://quickform.cn(若自建部署,请替换为您自己的站点根地址) - 认证方式:所有 CLI 接口均在请求体中传递 用户名 + 密码,或 用户名 + 授权码(
auth_code)(在个人中心「QFLink授权码」生成,类似 QQ 邮箱授权码),不依赖 Cookie/Session - 两种凭据完全等价:不存在「某些接口只支持密码」的情况。
/cli/list、/cli/add、/cli/show、/cli/export_task、/cli/upload等任务管理接口同样接受auth_code;只要在请求体里给出username与password、auth_code中的任意一个即可。 - 请求格式:支持 JSON(
Content-Type: application/json)或 表单(application/x-www-form-urlencoded) - 响应格式:一般为 JSON。
- 安全限制:为保护账号安全,短时间内连续认证失败可能会被暂时限制请求频率(返回
429,并包含retry_after秒数)。 - 教师认证:CLI 与 QFLink 仅对已认证教师开放(管理员除外)。未认证账号无论使用 用户名+密码 还是 QFLink 授权码 调用
/cli/*、/mcp/*(含POST /cli/qflink/verify)均返回 403,code: certification_required,并附带certification_url与说明;个人中心生成 QFLink 授权码亦需先完成认证。
用户名含中文、特殊 Unicode
- 请使用 UTF-8 编码发送请求;JSON 方式(
Content-Type: application/json)对中文最稳妥。 - 表单方式请使用
application/x-www-form-urlencoded; charset=utf-8(或依赖客户端默认 UTF-8)。 - 服务端会对
username做 Unicode NFC 规范化、去除首尾空白与常见零宽字符,并尝试纠正常见的「UTF-8 被误按 Latin-1 解码」乱码,以便与站内已注册用户名一致。 - 密码不做空白裁剪,请原样传输。
说明:本文档涵盖两类能力
- CLI 接口(/cli/*):给“校园版/教师版迁移、脚本、大模型工具”调用的账号凭据接口(用户名 + 密码,或 用户名 + QFLink 授权码,两者等价;无需 Cookie)。
- 网页端「任务导出 / 导入」:站内按钮触发的导出 ZIP / 导入 ZIP|JSON(需要网页登录)。
2. 获取当前用户信息 POST /cli/getuser
使用「用户名 + 密码」或「用户名 + QFLink 授权码」认证,返回账号资料(不写 Session,适合脚本判断认证状态)。
请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| username | 是 | 用户名(也可用已绑定的邮箱/手机号登录) |
| password | 与 auth_code 二选一 | 密码 |
| auth_code | 与 password 二选一 | QFLink 授权码(qf + 32 位十六进制) |
成功响应(200)
{
"success": true,
"user": {
"id": 12,
"username": "teacher1",
"email": "teacher@example.com",
"email_verified": true,
"phone": "13800138000",
"school": "某某中学",
"school_province": "浙江省",
"role": "user",
"is_certified": true,
"certified_at": "2025-03-01 10:00:00",
"task_limit": 3,
"created_at": "2024-09-01 08:00:00"
}
}
说明:
school为个人资料中的单位/学校。is_certified为是否已通过教师认证。- 未绑定真实邮箱时,
email可能为空字符串(占位邮箱不返回)。
错误响应
400:缺少参数401:用户名、密码或 QFLink 授权码不正确429:认证尝试过于频繁
示例(curl)
curl -X POST "https://quickform.cn/cli/getuser" \
-H "Content-Type: application/json" \
-d '{"username":"teacher1","password":"your_password"}'
(兼容旧路径:POST /mcp/getuser。)
2.1 QFLink 校验 POST /cli/qflink/verify
教师版/校园版连接在线服务器时使用;认证参数同 getuser,另可加 client(teacher / school)。
成功时返回 user 与 qflink.online_base、qflink.cli_endpoints。详见 QFLINK.md。
未认证教师(用户名+密码或授权码)示例响应(403):
{
"success": false,
"code": "certification_required",
"message": "该账号尚未完成教师认证,无法使用 QFLink / CLI 连接在线版。用户名+密码与 QFLink 授权码均不可用,请先完成教师认证。",
"is_certified": false,
"certification_url": "https://quickform.cn/certification/request",
"hint": "请登录在线版个人中心提交「教师认证」申请,审核通过后再从校园版/教师版重试。"
}
3. 增加数据任务 POST /cli/add
创建一条新的数据任务,并返回用于提交数据的 apiid。
请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| username | 是 | 用户名 |
| password | 与 auth_code 二选一 | 密码 |
| auth_code | 与 password 二选一 | QFLink 授权码(qf + 32 位十六进制) |
| task_name | 是 | 任务名称 |
| task_intro | 否 | 任务介绍/描述 |
(兼容字段:title 等同 task_name,description 等同 task_intro。)
成功响应(200)
{
"success": true,
"apiid": "a1b2c3d4ef"
}
apiid 即该任务的 API 标识,后续提交数据、拉取数据都使用此 id。
错误响应
400:缺少必填参数 →{ "success": false, "message": "缺少 username" }或{ "success": false, "message": "缺少 password 或 auth_code" }401:用户名、密码或 QFLink 授权码不正确 →{ "success": false, "message": "用户名或密码错误" }/{ "success": false, "message": "用户名或授权码错误" }403:已达任务数量上限 →{ "success": false, "message": "已达任务数量上限(当前 N 个)..." }403:从第二个任务起需先绑定/验证邮箱 →{ "success": false, "code": "email_not_bound" | "email_not_verified", "message": "..." }500:服务器异常 →{ "success": false, "message": "..." }
示例(curl)
# JSON
curl -X POST "https://quickform.cn/cli/add" \
-H "Content-Type: application/json" \
-d '{"username":"teacher1","password":"your_password","task_name":"课堂签到表","task_intro":"本周签到"}'
# 表单
curl -X POST "https://quickform.cn/cli/add" \
-d "username=teacher1&password=your_password&task_name=课堂签到表&task_intro=本周签到"
4. 查看数据任务列表 POST /cli/list
获取当前账号下所有数据任务及其 apiid 与名称。
请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| username | 是 | 用户名 |
| password | 与 auth_code 二选一 | 密码 |
| auth_code | 与 password 二选一 | QFLink 授权码(qf + 32 位十六进制) |
成功响应(200)
{
"success": true,
"tasks": [
{ "apiid": "a1b2c3d4ef", "name": "课堂签到表" },
{ "apiid": "x9y8z7w6vu", "name": "问卷回收" }
]
}
错误响应
400:缺少 username,或password与auth_code都没提供401:用户名、密码或 QFLink 授权码不正确
示例(curl)
curl -X POST "https://quickform.cn/cli/list" \
-H "Content-Type: application/json" \
-d '{"username":"teacher1","password":"your_password"}'
5. 查看单个任务详情(用于迁移导出端)POST /cli/show
通过 apiid 获取任务的基本信息与附件(用于“校园版/教师版”从在线版拉取任务并下载 HTML 附件)。
请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| username | 是 | 用户名 |
| password | 与 auth_code 二选一 | 密码 |
| auth_code | 与 password 二选一 | QFLink 授权码(qf + 32 位十六进制) |
| apiid | 是 | 任务 API 标识 |
| include_data | 否 | true 时额外返回 submissions 数组(仅任务所有者;公开任务不可用)。不计入 /all 配额,禁读模式下仍可用。 |
成功响应(200)
{
"success": true,
"apiid": "a1b2c3d4ef",
"name": "课堂签到表",
"intro": "任务描述(可空)",
"tutorial": "教程链接(可空)",
"share_url": "分享链接(可空)",
"attachments": [
{ "name": "index.html", "url": "https://quickform.cn/static/uploads/xxxxxxxx.html" }
],
"submissions": [],
"total_submissions": 0
}
(无 include_data 时不含 submissions / total_submissions。)
attachments 重要要求(迁移导出端必读)
attachments应包含该任务的 HTML/HTM 页面附件(至少 1 个也可以)。attachments[].url必须是 无需 Cookie/Session、无需登录即可下载的直链(否则导入端无法下载并改写 HTML 内的 API 地址)。- 导入端通常只处理
.html/.htm;你也可以返回其它类型,但不会被迁移处理。
错误响应
400:缺少参数401:用户名、密码或 QFLink 授权码不正确404:任务不存在或无权限
示例(curl)
curl -X POST "https://quickform.cn/cli/show" \
-H "Content-Type: application/json" \
-d '{"username":"teacher1","password":"your_password","apiid":"a1b2c3d4ef"}'
含提交数据(所有者,JSON 内联,适合条数较少时):
curl -X POST "https://quickform.cn/cli/show" \
-H "Content-Type: application/json" \
-d '{"username":"teacher1","password":"your_password","apiid":"a1b2c3d4ef","include_data":true}'
5.1 导出任务迁移 ZIP POST /cli/export_task
与网页「导出任务」相同,返回 application/zip 附件(v2 仅结构,v3 含 submissions.json 与附件目录)。
- 权限:任务所有者或管理员
- 不计入
GET /api/<apiid>/all的读取次数与流量配额(适用于配额已用尽时备份/迁移) - 禁读模式下仍允许导出(对外 API 仍禁读)
- 需启用
TASK_MIGRATION_ACTIVE(默认开启)
请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| username | 是 | 用户名 |
| password | 与 auth_code 二选一 | 密码 |
| auth_code | 与 password 二选一 | QFLink 授权码(qf + 32 位十六进制) |
| apiid | 是 | 任务 API 标识(也可用 task_id / id) |
| include_data | 否 | true 时导出含全部提交数据(默认 false 仅 HTML+manifest) |
成功响应(200)
- Content-Type:
application/zip - Content-Disposition:附件文件名
- 响应头:
X-QuickForm-Export-Include-Data、X-QuickForm-Task-Apiid
错误响应
400/401/404:同/cli/show403:禁读且策略不允许(当前站内导出通道对所有者开放)413:ZIP 超过TASK_MIGRATION_ZIP_MAX_BYTES503:任务迁移功能未启用
示例(curl,含数据保存为文件)
curl -X POST "https://quickform.cn/cli/export_task" \
-H "Content-Type: application/json" \
-d '{"username":"teacher1","password":"your_password","apiid":"a1b2c3d4ef","include_data":true}' \
-o task_migration.zip
6. 上传 HTML 文件 POST /cli/upload
上传单个 HTML/HTM 文件,并绑定到某个已创建的任务(用于迁移导入端:后续需要带 taskid 的可访问页面)。
说明:CLI 上传时必须指定目标任务(
apiid推荐 /task_id或taskid/id)。否则会出现“未走教师认证/任务权限校验就拿到可访问公网 HTML”的问题。
请求方式
- Content-Type:
multipart/form-data - 参数:
username、以及password或auth_code(表单字段,二者二选一)apiid(推荐)/task_id(或taskid)/id(数据库ID,二选一:三者其一即可)file(文件字段,仅支持 .html / .htm,单文件最大 4MB)
成功响应(200)
{
"success": true,
"url": "https://quickform.cn/uploads/xxxxxxxx.html?taskid=a1b2c3d4ef",
"filename": "xxxxxxxx.html"
}
url:该文件的公网访问地址,可直接在浏览器或前端 iframe 中打开。url:在未通过教师认证(或未满足任务 HTML 审核条件)时,访问页面会显示“审核中/未通过”提示页,不会直接返回原始 HTML。filename:服务器保存后的文件名(随机命名,避免冲突)。
若你需要该上传结果马上用于迁移导入/展示,请确保当前账号已满足“教师认证通过/任务 HTML 可访问”条件。
错误响应
400:缺少参数、未选择文件、未提供目标任务参数(apiid/task_id/id任意一个)、或文件格式/大小不符合(仅允许 .html/.htm,单文件 ≤ 4MB)→{ "success": false, "message": "..." }401:用户名、密码或 QFLink 授权码不正确403:目标任务不存在或无权限(非任务所有者/无管理员权限)500:服务器保存失败
示例(curl)
curl -X POST "https://quickform.cn/cli/upload" \
-F "username=teacher1" \
-F "password=your_password" \
-F "apiid=a1b2c3d4ef" \
-F "file=@/path/to/your/page.html"
7. 使用 apiid 提交与获取数据
拿到 apiid 后,与网页端一致:
- 提交一条数据:
POST /api/<apiid> - Body:JSON 对象,例如
{"name":"张三","score":85} -
成功:
{ "message": "提交成功", "status": "success" } -
获取全部提交数据:
GET /api/<apiid>/all -
返回:
{ "submissions": [ ... ], "total_submissions": N } -
简要查询(最新 3 条):
GET /api/<apiid> - 返回:含
submissions、total_submissions、task_id、task_title等
高并发与网页优先(自建部署):当 POST /api/<apiid>、GET /api/<apiid>/all 等数据通道瞬时占满 Waitress 工作线程时,进程内可对上述路由施加有界并发。POST /api/<apiid>(JSON 或 application/x-www-form-urlencoded,非 multipart)在槽位已满时默认将已解析数据写入本地临时队列并返回 202(queued: true、spool_id),后台线程在有空槽时写入数据库;若关闭落盘(QF_API_POST_SPOOL_ON_BUSY=0)或队列目录积压超过上限,则仍返回 503(含 retry_after)。GET /api/<apiid>/all 等仍以 503 退避为主。环境变量:QF_BULK_API_MAX_INFLIGHT(0 关闭)、QF_WEB_IN_FLIGHT_RESERVE、QF_BULK_API_RETRY_AFTER、QF_API_POST_SPOOL_*(见 core/api_submit_spool.py)。详见 core/bulk_api_gate.py 注释。
完整提交地址示例:https://quickform.cn/api/a1b2c3d4ef
8. 与扣子 / OpenClaw 的自动化流程
- 创建任务:调用
POST /cli/add,传入用户名与密码(或 QFLink 授权码)、任务名称(及可选介绍),得到apiid。 - 配置提交地址:在扣子/OpenClaw 应用中将「数据提交接口」配置为:
https://quickform.cn/api/<apiid>
例如:https://quickform.cn/api/a1b2c3d4ef - 应用内提交:用户在前端填写的数据以 JSON 形式 POST 到上述地址即可写入 QuickForm。
- 查询任务列表:需要展示或选择「往哪个任务提交」时,可调用
POST /cli/list获取当前用户下所有apiid与名称。
这样即可在不打开 QuickForm 网页的情况下,完成任务的创建、列表查看与数据提交地址的配置。
9. 网页端「任务导出 / 导入」(站内功能)
如果你是在网页里操作(不是脚本/CLI),请看这里。
8.1 开关
管理员可用环境变量控制是否启用:
- 启用:默认即启用,或设置
TASK_MIGRATION_ACTIVE=1 - 关闭:设置
TASK_MIGRATION_ACTIVE=0
8.2 导出任务(ZIP)
- 入口:任务详情页 / 仪表盘
- 「导出任务」:仅任务结构与 HTML(v2)
- 「导出含数据」:供校园版迁移,含全部提交记录(v3)
- 路由:
GET /task/<task_id>/export_template— 不含提交数据GET /task/<task_id>/export_template_with_data— 含提交数据- 产物(v2):
quickform-task-migration.json、html/下页面文件 - 产物(v3,在 v2 基础上增加):
submissions.json:提交数组,每项含legacy_id、submitted_at、dataattachments/:多模态等字段中的附件文件(data.attachment内 URL 已改写为包内相对路径)
环境变量(可选):
TASK_MIGRATION_ZIP_MAX_BYTES:ZIP 总体积上限(默认 50MB)TASK_MIGRATION_EXPORT_MAX_SUBMISSIONS:单次最多导出条数,0表示不限制
注意:导出通常仅任务创建者/管理员可用;含数据导出走站内/CLI 所有者通道,不因「禁读」或
/all配额用尽而拒绝(公开 API 的/all仍受配额限制)。在线版不负责将 v3 包导入为提交记录,由校园版自行消费 ZIP。
8.3 导入任务(ZIP 或 JSON)
- 入口:仪表盘/任务详情页弹窗 「导入任务」
- 路由:
POST /task/import_template(multipart/form-data) - 支持:
- ZIP(v2):由本站“任务导出”生成;导入后会分配新的 APIID,并按选项改写 HTML 内
/api/<old>→/api/<new>(可选同时替换站点根地址)。 - JSON(v1):旧版模板,仅任务基本信息,不含 HTML 与提交数据。
10. 返回数据格式小结
| 接口 | 成功时返回字段 | 说明 |
|---|---|---|
| POST /cli/getuser | success: true, user |
用户信息(认证、单位、邮箱等) |
| POST /cli/add | success: true, apiid |
新任务的 API 标识 |
| POST /cli/list | success: true, tasks |
tasks 为 [{ apiid, name }, ...] |
| POST /cli/show | success: true, attachments |
迁移导出端:返回 HTML 附件直链;include_data 可拉 JSON |
| POST /cli/export_task | ZIP 文件流 | 与网页「导出任务」一致;include_data=true 含全部数据,不计 /all 配额 |
| POST /cli/upload | success: true, url, filename |
上传并绑定到任务的可访问页面地址与保存文件名(未认证时返回审核提示页) |
所有错误均为 success: false 且带 message 字段,便于 CLI 或技能内统一处理。

浙公网安备 33010602011771号