From 9e81e6b15c71e40020b1cfbd4d48e8b84be7a6bc Mon Sep 17 00:00:00 2001 From: wuduoyi Date: Tue, 24 Oct 2023 12:23:55 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E8=A1=A5=E5=85=85=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=20fetcher=20=E6=97=B6=E5=8F=AF=E8=83=BD=E6=BC=8F?= =?UTF-8?q?=E4=BA=86=20attachmentAdpator=20=E5=AE=9E=E7=8E=B0=E7=9A=84?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-CN/types/api.md | 7 ++ examples/components/SchemaRender.jsx | 64 +++++++++++++---- mock/cfc/index.js | 12 ++++ mock/cfc/mock/download.zip | Bin 0 -> 857 bytes mock/cfc/mock/index.js | 98 +++++++++++++++------------ mock/index.js | 4 +- 6 files changed, 124 insertions(+), 61 deletions(-) create mode 100644 mock/cfc/mock/download.zip diff --git a/docs/zh-CN/types/api.md b/docs/zh-CN/types/api.md index 5f852e81f..de89f2ecf 100755 --- a/docs/zh-CN/types/api.md +++ b/docs/zh-CN/types/api.md @@ -871,6 +871,13 @@ Content-Disposition: attachment; filename="download.pdf" Access-Control-Expose-Headers: Content-Disposition ``` +如果自己覆盖了 `fetcher` 函数,需要有类似如下代码,具体可以参考 `embed.tsx` 里的实现 + +```javascript +let response = await axios(config); +response = await attachmentAdpator(response, __); +``` + ### 配置提示信息 可以通过`messages`自定义接口请求提示信息。 diff --git a/examples/components/SchemaRender.jsx b/examples/components/SchemaRender.jsx index 172960569..02affd385 100644 --- a/examples/components/SchemaRender.jsx +++ b/examples/components/SchemaRender.jsx @@ -5,7 +5,7 @@ import Portal from 'react-overlays/Portal'; import {normalizeLink} from 'amis-core'; import {withRouter} from 'react-router'; import copy from 'copy-to-clipboard'; -import {qsparse, parseQuery} from 'amis-core'; +import {qsparse, parseQuery, attachmentAdpator} from 'amis-core'; import isPlainObject from 'lodash/isPlainObject'; function loadEditor() { @@ -106,16 +106,29 @@ export default function (schema, schemaProps, showCode, envOverrides) { return false; }, - fetcher: ({url, method, data, config, headers}) => { + fetcher: async ({ + url, + method, + data, + responseType, + config, + headers + }) => { config = config || {}; - config.headers = headers || {}; + config.url = url; + responseType && (config.responseType = responseType); if (config.cancelExecutor) { config.cancelToken = new axios.CancelToken(config.cancelExecutor); } - if (data && data instanceof FormData) { - // config.headers = config.headers || {}; + config.headers = headers || {}; + config.method = method; + config.data = data; + + if (method === 'get' && data) { + config.params = data; + } else if (data && data instanceof FormData) { // config.headers['Content-Type'] = 'multipart/form-data'; } else if ( data && @@ -127,19 +140,40 @@ export default function (schema, schemaProps, showCode, envOverrides) { config.headers['Content-Type'] = 'application/json'; } - if (method !== 'post' && method !== 'put' && method !== 'patch') { - if (data) { - if (method === 'delete') { - config.data = data; - } else { - config.params = data; - } - } + // 支持返回各种报错信息 + config.validateStatus = function () { + return true; + }; - return axios[method](url, config); + let response = await axios(config); + response = await attachmentAdpator(response, s => { + return s; + }); + + if (response.status >= 400) { + if (response.data) { + // 主要用于 raw: 模式下,后端自己校验登录, + if ( + response.status === 401 && + response.data.location && + response.data.location.startsWith('http') + ) { + location.href = response.data.location.replace( + '{{redirect}}', + encodeURIComponent(location.href) + ); + return new Promise(() => {}); + } else if (response.data.msg) { + throw new Error(response.data.msg); + } else { + throw new Error(JSON.stringify(response.data, null, 2)); + } + } else { + throw new Error(`${response.status}`); + } } - return axios[method](url, data, config); + return response; }, isCancel: value => axios.isCancel(value), copy: (content, options) => { diff --git a/mock/cfc/index.js b/mock/cfc/index.js index 143e2d791..53c3d0c07 100755 --- a/mock/cfc/index.js +++ b/mock/cfc/index.js @@ -49,6 +49,18 @@ function mockResponse(event, context, callback) { json: false, body: res }); + }, + download(file) { + callback(null, { + statusCode: 200, + headers: { + ...createHeaders(event.headers), + 'Content-Type': 'application/octet-stream', + 'Content-Disposition': `attachment; filename="${file}"` + }, + json: false, + download: file + }); } }; } diff --git a/mock/cfc/mock/download.zip b/mock/cfc/mock/download.zip new file mode 100644 index 0000000000000000000000000000000000000000..c572e247670cdd33bc0a5ffe66f826cd6c4ed896 GIT binary patch literal 857 zcmWIWW@Zs#-~htxrg@9*0 zWckX-zyQ?Ez_2yc*Z;PIz~1NKZx|n%y1d@9oXcgk7YpZ=pw0`y!4ozfKN(bQ{>GhK z=}w^k-fvgreqCR2rT*g0ukJGJj!U`ZWzxU@JUiRm__YgH?g<^U;7!gVF%jz;*xuC( zK3Uq2hpY1-yCY%m6W%TD}ue$JGZLb z(rVf;P=>7z$m_t$Sx zjW{&v{7(68ElV3rE(oX;8nyEGeSQ3G)uT<-ck_0<*e&|9;ACK7 zHkai1XWjj_b5_%~7t4(oX5G4~SmUHF*L_oNw#&^DncmB1x1M`4;cIEVnn=Pjqp!wN zZ}{%>^tXGn` item.label.substring(0, term.length) === term); - } - - return res.json(json); - } else if (/^sample/.test(subpath)) { - let file = require.resolve(path.join(DIRNAME, 'sample.js')); - delete require.cache[file]; - return require(file)(req, res); - } else if (exist(jsFile)) { - let file = require.resolve(path.join(DIRNAME, jsFile)); - delete require.cache[file]; - - if (req.query.waitSeconds) { - return setTimeout(function() { - require(file)(req, res); - }, parseInt(req.query.waitSeconds, 10) * 1000); - } - - return require(file)(req, res); - } if (exist(jsonFile)) { - if (req.query.waitSeconds) { - return setTimeout(function() { - res.json(readJson(jsonFile)); - }, parseInt(req.query.waitSeconds, 10) * 1000); - } - - return res.json(readJson(jsonFile)); - } else if (/crud\/\d+$/.test(subpath) && req.method === 'DELETE') { - return res.json({ - status: 0, - msg: '删除成功' - }) + if (term) { + json.data = json.data.filter( + item => item.label.substring(0, term.length) === term + ); } - res.json(readJson('notFound.json')); -} + return res.json(json); + } else if (/^sample/.test(subpath)) { + let file = require.resolve(path.join(DIRNAME, 'sample.js')); + delete require.cache[file]; + return require(file)(req, res); + } else if (exist(jsFile)) { + let file = require.resolve(path.join(DIRNAME, jsFile)); + delete require.cache[file]; + + if (req.query.waitSeconds) { + return setTimeout(function () { + require(file)(req, res); + }, parseInt(req.query.waitSeconds, 10) * 1000); + } + + return require(file)(req, res); + } + if (exist(jsonFile)) { + if (req.query.waitSeconds) { + return setTimeout(function () { + res.json(readJson(jsonFile)); + }, parseInt(req.query.waitSeconds, 10) * 1000); + } + + return res.json(readJson(jsonFile)); + } else if (/crud\/\d+$/.test(subpath) && req.method === 'DELETE') { + return res.json({ + status: 0, + msg: '删除成功' + }); + } else if (/download/.test(subpath)) { + return res.download(path.join(DIRNAME, 'download.zip')); + } + + res.json(readJson('notFound.json')); +}; function exist(subpath) { - return fs.existsSync(path.join(DIRNAME, subpath)); + return fs.existsSync(path.join(DIRNAME, subpath)); } function readJson(subpath) { - const content = fs.readFileSync(path.join(DIRNAME, subpath), 'utf8'); - return JSON.parse(content); + const content = fs.readFileSync(path.join(DIRNAME, subpath), 'utf8'); + return JSON.parse(content); } diff --git a/mock/index.js b/mock/index.js index 46828558c..a0bd27a30 100644 --- a/mock/index.js +++ b/mock/index.js @@ -26,7 +26,9 @@ module.exports = function (req, res) { res.status(500).json({status: 500, msg: err}); } else { res.set(result.headers); - if (!result.json) { + if (result.download) { + res.download(result.download); + } else if (!result.json) { res.status(result.statusCode).send(result.body); } else { res.status(result.statusCode).json(JSON.parse(result.body));