feat: 优化 api 对 graphql 的支持 (#3819)

This commit is contained in:
吴多益 2022-03-22 12:24:03 +08:00 committed by GitHub
parent 34870ac711
commit b929a1a351
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 137 additions and 0 deletions

View File

@ -98,6 +98,14 @@ CRUD即增删改查组件主要用来展现数据列表并支持各类
> 如果 api 地址中有变量,比如 `/api/mock2/sample/${id}`amis 就不会自动加上分页参数,需要自己加上,改成 `/api/mock2/sample/${id}?page=${page}&perPage=${perPage}` > 如果 api 地址中有变量,比如 `/api/mock2/sample/${id}`amis 就不会自动加上分页参数,需要自己加上,改成 `/api/mock2/sample/${id}?page=${page}&perPage=${perPage}`
## 分页参数
默认的分页参数是 `page``perPage`page 代表页数比如第一页perPage 代表每页显示几行。
如果要其它格式,比如转成 `limit``offset`,可以使用公式来转换,比如
`/api/mock2/sample?limit=${perPage}&offset=${(page - 1) * perPage}`
## 功能 ## 功能
既然这个渲染器叫增删改查,那接下来分开介绍这几个功能吧。 既然这个渲染器叫增删改查,那接下来分开介绍这几个功能吧。

View File

@ -938,6 +938,101 @@ Access-Control-Expose-Headers: Content-Disposition
} }
``` ```
## GraphQL
1.7.0 及之前的版本需要通过配置 `data` 里的 `query``variables` 字段可以实现 GraphQL 查询
```schema: scope="body"
{
"type": "form",
"api": {
"method": "post",
"url": "/api/mock2/form/saveForm",
"data": {
"query": "mutation AddUser($name: String!, $email: String!) { \
insert_user(object: { title: $title, email: $email }) { \
title \
email \
} \
}",
"variables": {
"name": "${name}",
"email": "${email}"
}
}
},
"body": [
{
"type": "input-text",
"name": "name",
"label": "姓名:"
},
{
"name": "email",
"type": "input-email",
"label": "邮箱:"
}
]
}
```
1.8.0 及以上版本简化了 GraphQL 的支持,增加了 `graphql` 属性,如果配置了就会自动并自动将 data 当成 `variables`,上面的例子可以简化为下面的写法,除了简化之外还方便了可视化编辑器编辑
```schema: scope="body"
{
"type": "form",
"api": {
"method": "post",
"url": "/api/mock2/form/saveForm",
"graphql": "mutation AddUser($name: String!, $email: String!) { \
insert_user(object: { name: $name, email: $email }) { \
name \
email \
} \
}"
},
"body": [
{
"type": "input-text",
"name": "name",
"label": "姓名:"
},
{
"name": "email",
"type": "input-email",
"label": "邮箱:"
}
]
}
```
如果设置了 `data` 会被当成 `variables`,比如在 CRUD 里设置分页参数,比如下面的例子
```json
{
"type": "crud",
"api": {
"url": "/api/mock2/sample",
"method": "post",
"graphql": "{ pages(page: $page, perPage: $perPage) { id, engine } }",
"data": {
"page": "${page}",
"perPage": "${perPage}"
}
},
"columns": [
{
"name": "id",
"label": "ID"
},
{
"name": "engine",
"label": "Rendering engine"
}
]
}
```
## 属性表 ## 属性表
| 字段名 | 说明 | 类型 | 备注 | | 字段名 | 说明 | 类型 | 备注 |

View File

@ -25,6 +25,12 @@ module.exports = function (req, res) {
return bulkUpdate2(req, res); return bulkUpdate2(req, res);
} else if (pathname === 'sample/mirror') { } else if (pathname === 'sample/mirror') {
return mirror(req, res); return mirror(req, res);
} else if (pathname === 'sample/array') {
return res.json(DB.concat());
} else if (pathname === 'sample/itemsHasAnother') {
return res.json({myItems: DB.concat()});
} else if (pathname === 'sample/arrayInData') {
return res.json({data: DB.concat()});
} }
return index(req, res); return index(req, res);

View File

@ -272,6 +272,16 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
items = result.items || result.rows; items = result.items || result.rows;
} }
// 如果不按照 items 格式返回,就拿第一个数组当成 items
if (!Array.isArray(items)) {
for (const key of Object.keys(result)) {
if (result.hasOwnProperty(key) && Array.isArray(result[key])) {
items = result[key];
break;
}
}
}
if (!Array.isArray(items)) { if (!Array.isArray(items)) {
throw new Error(self.__('CRUD.invalidArray')); throw new Error(self.__('CRUD.invalidArray'));
} else { } else {

View File

@ -6,6 +6,8 @@ export interface ApiObject extends SchemaApiObject {
withCredentials?: boolean; withCredentials?: boolean;
cancelExecutor?: (cancel: Function) => void; cancelExecutor?: (cancel: Function) => void;
}; };
graphql?: string;
operationName?: string;
body?: PlainObject; body?: PlainObject;
query?: PlainObject; query?: PlainObject;
adaptor?: (payload: object, response: fetcherResult, api: ApiObject) => any; adaptor?: (payload: object, response: fetcherResult, api: ApiObject) => any;

View File

@ -172,6 +172,22 @@ export function buildApi(
} }
} }
if (api.graphql) {
if (api.method === 'get') {
api.query = api.data = {...api.query, query: api.graphql};
} else if (
api.method === 'post' ||
api.method === 'put' ||
api.method === 'patch'
) {
api.body = api.data = {
query: api.graphql,
operationName: api.operationName,
variables: cloneObject(api.data)
};
}
}
return api; return api;
} }