From f3316312b7122794845f4f4b069825fc34b4d466 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Thu, 8 May 2025 22:33:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0fetcher=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 + pnpm-lock.yaml | 118 +++++++++++++++++++++++++++++++++++++++++++++ src/pages/Home.tsx | 9 +++- src/util/amis.ts | 93 ++++++++++++++++++++++++++++++++++- 4 files changed, 220 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9003e8c..d966c80 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,11 @@ }, "dependencies": { "@ant-design/icons": "^6.0.0", + "@ant-design/x": "^1.2.0", "@tinyflow-ai/react": "^0.1.6", "amis": "^6.12.0", "antd": "^5.25.0", + "axios": "^1.9.0", "licia": "^1.48.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 83b0bc2..c002595 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@ant-design/icons': specifier: ^6.0.0 version: 6.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@ant-design/x': + specifier: ^1.2.0 + version: 1.2.0(antd@5.25.0(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tinyflow-ai/react': specifier: ^0.1.6 version: 0.1.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(svelte@5.28.2) @@ -20,6 +23,9 @@ importers: antd: specifier: ^5.25.0 version: 5.25.0(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + axios: + specifier: ^1.9.0 + version: 1.9.0 licia: specifier: ^1.48.0 version: 1.48.0 @@ -112,6 +118,13 @@ packages: peerDependencies: react: '>=16.9.0' + '@ant-design/x@1.2.0': + resolution: {integrity: sha512-sV+C6ER+xn6XQF3gYN3Ma9MnK8Bcfj+5C4cRvtKNvzExHwC6laBD1g6TWHH7vFPDOQUhYlJT4tw+NdcvZJx/ZA==} + peerDependencies: + antd: ^5.20.3 + react: '>=18.0.0' + react-dom: '>=18.0.0' + '@babel/runtime@7.27.1': resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} engines: {node: '>=6.9.0'} @@ -961,10 +974,16 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + attr-accept@2.2.2: resolution: {integrity: sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==} engines: {node: '>=4'} + axios@1.9.0: + resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -1096,6 +1115,10 @@ packages: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + compress-commons@4.1.2: resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} engines: {node: '>= 10'} @@ -1226,6 +1249,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -1300,6 +1327,10 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + es6-promise@4.2.8: resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} @@ -1465,6 +1496,19 @@ packages: peerDependencies: react: ^15.0.2 || ^16.0.0 || ^17.0.0 + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -1554,6 +1598,10 @@ packages: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} @@ -1826,10 +1874,18 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + mime-db@1.54.0: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mime-types@3.0.1: resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} engines: {node: '>= 0.6'} @@ -2067,6 +2123,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2972,6 +3031,21 @@ snapshots: resize-observer-polyfill: 1.5.1 throttle-debounce: 5.0.2 + '@ant-design/x@1.2.0(antd@5.25.0(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@ant-design/colors': 7.2.0 + '@ant-design/cssinjs': 1.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@ant-design/cssinjs-utils': 1.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@ant-design/fast-color': 2.0.6 + '@ant-design/icons': 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@babel/runtime': 7.27.1 + antd: 5.25.0(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@babel/runtime@7.27.1': {} '@emotion/hash@0.8.0': {} @@ -3907,8 +3981,18 @@ snapshots: async@3.2.6: {} + asynckit@0.4.0: {} + attr-accept@2.2.2: {} + axios@1.9.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axobject-query@4.1.0: {} balanced-match@1.0.2: {} @@ -4040,6 +4124,10 @@ snapshots: color-support@1.1.3: optional: true + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + compress-commons@4.1.2: dependencies: buffer-crc32: 0.2.13 @@ -4155,6 +4243,8 @@ snapshots: deep-is@0.1.4: {} + delayed-stream@1.0.0: {} + delegates@1.0.0: optional: true @@ -4224,6 +4314,13 @@ snapshots: dependencies: es-errors: 1.3.0 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + es6-promise@4.2.8: {} esbuild@0.25.4: @@ -4483,6 +4580,15 @@ snapshots: transitivePeerDependencies: - encoding + follow-redirects@1.15.9: {} + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + forwarded@0.2.0: {} frac@1.1.2: {} @@ -4574,6 +4680,10 @@ snapshots: has-symbols@1.1.0: {} + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + has-unicode@2.0.1: optional: true @@ -4811,8 +4921,14 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mime-types@3.0.1: dependencies: mime-db: 1.54.0 @@ -5025,6 +5141,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} + punycode@2.3.1: {} pure-color@1.3.0: {} diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 236ec61..fa21244 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -8,7 +8,14 @@ function Home() { type: 'page', title: 'Home Page', body: [ - 'Hello amis' + { + type: 'service', + api: 'http://baidu.com', + body: { + type: 'tpl', + tpl: 'hello world', + } + } ] } )} diff --git a/src/util/amis.ts b/src/util/amis.ts index 9b9bf89..5c139cc 100644 --- a/src/util/amis.ts +++ b/src/util/amis.ts @@ -1,10 +1,28 @@ import type {Schema} from 'amis' -import {render} from 'amis' +import {attachmentAdpator, makeTranslator, render} from 'amis' +import axios from 'axios' import 'amis/lib/themes/antd.css' import 'amis/lib/helper.css' import 'amis/sdk/iconfont.css' +const __ = makeTranslator('zh'); + +const responseAdaptor = () => (response: any) => { + let payload = response.data || {}; // blob 下可能会返回内容为空? + if (payload.hasOwnProperty('errno')) { + payload.status = payload.errno; + payload.msg = payload.errmsg; + } else if (payload.hasOwnProperty('no')) { + payload.status = payload.no; + payload.msg = payload.error; + } + return { + ...response, + data: payload + }; +} + export const amisRender = (schema: Schema) => { return render( schema, @@ -14,5 +32,78 @@ export const amisRender = (schema: Schema) => { }, theme: 'antd', }, + { + fetcher: async (api: any) => { + let {url, method, data, responseType, config, headers} = api; + config = config || {}; + config.url = url; + config.withCredentials = true; + responseType && (config.responseType = responseType); + + if (config.cancelExecutor) { + config.cancelToken = new (axios as any).CancelToken( + config.cancelExecutor + ); + } + + 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 && + typeof data !== 'string' && + !(data instanceof Blob) && + !(data instanceof ArrayBuffer) + ) { + data = JSON.stringify(data); + config.headers['Content-Type'] = 'application/json'; + } + + // 支持返回各种报错信息 + config.validateStatus = function () { + return true; + }; + + let response = await axios(config); + response = await attachmentAdpator(response, __, api); + response = responseAdaptor()(response); + + 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( + 'System.requestError' + JSON.stringify(response.data, null, 2) + ); + } + } else { + throw new Error( + `${'System.requestErrorStatus'} ${response.status}` + ); + } + } + + return response; + }, + isCancel: (value: any) => (axios as any).isCancel(value), + } ) } \ No newline at end of file