diff --git a/README.en-US.md b/README.en-US.md index b2238c8..854068e 100644 --- a/README.en-US.md +++ b/README.en-US.md @@ -16,6 +16,10 @@ The Alibaba Cloud API Toolkit for VSCode makes it easier to access Alibaba Cloud including descriptions, request parameters, response parameters and error codes. Click to debug, you can link to Aliyun OpenAPI portal for online API trial. +* **Call the API:** You can use the form to call the Alibaba Cloud API and see the response. + +* **SDK Code Sample:** You can get the SDK code samples and quickly open the corresponding SDK code in VS Code. + * More features are under development, please stay tuned. ## Extension UI Guide @@ -30,3 +34,36 @@ Click to debug, you can link to Aliyun OpenAPI portal for online API trial. ![API Serching](https://img.alicdn.com/imgextra/i1/O1CN01KaWkBF1UfCUkY0N3v_!!6000000002544-0-tps-1286-518.jpg) +* Call the API + +The feature requires you to configure your AK/SK information as follows: +1. Install [Alibaba Cloud CLI Tools](https://marketplace.visualstudio.com/items?itemName=alibabacloud-openapi.aliyuncli) extentions. +2. Open the command line to install aliyun-cli `brew install aliyun-cli`, +3. Enter `aliyun configure` and follow the prompts to configure it, +4. Click the Alibaba Cloud icon in VS Code status bar to manage your profiles, +5. More information please refer to the [Alibaba Cloud CLI Documentation] (https://github.com/aliyun/aliyun-cli?tab=readme-ov-file#configure). + +![API debug](https://img.alicdn.com/imgextra/i4/O1CN01F1qI7S1BunIFJPiAt_!!6000000000006-0-tps-2618-2050.jpg) + +* SDK Code Sample + +![sdk demo](https://img.alicdn.com/imgextra/i1/O1CN01GVhWTl1waRdYmCn7E_!!6000000006324-0-tps-2630-2038.jpg) + +## Requirements +- Need VS Code 1.75.0 or above. + +## Release Notes + +### 0.0.1 +Initial release +- Support product searching and subscription. +- Support API searching. +- Support API Document View. + +### 0.0.3 +- Support API calling. +- Support SDK code sample. + +## License + +See the [Apache License 2.0](./LICENSE). \ No newline at end of file diff --git a/README.md b/README.md index 12a714d..710f159 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,15 @@ Alibaba Cloud API Toolkit 是一个轻量化的阿里云 API 工具,支持在 * **API 文档预览:** 点击 API 可以打开一个新的标签页,并显示对应的 API 文档,包括描述、请求参数、响应参数和错误码。在文档中点击调试按钮,可以链接到阿里云 OpenAPI 门户进行在线 API 试用。 +* **API 调试:** 你可以在插件中使用表单的方式调试阿里云 API,并查看结果。 + +* **SDK 代码示例:** 你可以在插件中获得 SDK 代码示例,并在编辑器中快速打开对应的 SDK 代码。 + * 更多功能正在开发中,敬请期待... ## 插件 UI 导览 -![VSCode Extension Guide](https://img.alicdn.com/imgextra/i2/O1CN01VJNeqk1NKrbDtTotP_!!6000000001552-0-tps-2310-1524.jpg) +![VSCode Extension Guide](https://img.alicdn.com/imgextra/i1/O1CN01o9s4TT1GTq3oggW7K_!!6000000000624-0-tps-2456-1446.jpg) * 产品搜索 `ctrl+cmd+k` @@ -31,3 +35,36 @@ Alibaba Cloud API Toolkit 是一个轻量化的阿里云 API 工具,支持在 ![API Serching](https://img.alicdn.com/imgextra/i1/O1CN01KaWkBF1UfCUkY0N3v_!!6000000002544-0-tps-1286-518.jpg) +* API 调试 + +调试功能需要配置你的 AK/SK 信息,配置方法如下: +1. 安装 [Alibaba Cloud CLI Tools](https://marketplace.visualstudio.com/items?itemName=alibabacloud-openapi.aliyuncli) 插件, +2. 打开命令行安装 aliyun-cli `brew install aliyun-cli`, +3. 输入 `aliyun configure` 命令,按照提示进行配置, +4. 点击 VS Code 状态栏中的阿里云图标,管理你的 profiles, +5. 更多信息请参考 [Alibaba Cloud CLI Documentation](https://github.com/aliyun/aliyun-cli?tab=readme-ov-file#configure)。 + +![API debug](https://img.alicdn.com/imgextra/i4/O1CN01F1qI7S1BunIFJPiAt_!!6000000000006-0-tps-2618-2050.jpg) + +* SDK 示例 + +![sdk demo](https://img.alicdn.com/imgextra/i1/O1CN01GVhWTl1waRdYmCn7E_!!6000000006324-0-tps-2630-2038.jpg) + +## Requirements +- Need VS Code 1.75.0 or above. + +## Release Notes + +### 0.0.1 +Initial release +- Support product searching and subscription. +- Support API searching. +- Support API Document View. + +### 0.0.3 +- Support API calling. +- Support SDK code sample. + +## License + +See the [Apache License 2.0](./LICENSE). \ No newline at end of file diff --git a/media/package.json b/media/package.json index bf4a8a7..7f395f9 100644 --- a/media/package.json +++ b/media/package.json @@ -15,19 +15,21 @@ "@alicloud/console-components": "^1.6.2", "@monaco-editor/react": "^4.6.0", "@vercel/ncc": "^0.38.1", + "@vscode-elements/elements": "^1.0.0-pre.10", "antd": "^5.12.3", "intl-format": "^1.2.0", "load-script": "^2.0.0", + "lodash": "^4.17.20", "next": "^14.0.4", "pontx-ui": "latest", "react": "^18.2.0", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.2.0", + "react-use-observer": "^2.2.4", "sass": "^1.69.5", "semix-schema-table": "^0.1.3", "styled-components": "^6.1.1", - "xml2js": "^0.6.2", - "lodash": "^4.17.20" + "xml2js": "^0.6.2" }, "resolutions": { "semix-schema-table": "^0.1.3" @@ -44,6 +46,6 @@ "@types/react-dom": "^18.0.3", "@types/vscode": "^1.47.0", "@types/vscode-webview": "^1.57.0", - "@types/blueimp-md5":"^2.7.0" + "@types/blueimp-md5": "^2.7.0" } } diff --git a/media/src/components/APIPage/API.module.css b/media/src/components/APIPage/API.module.css new file mode 100644 index 0000000..265eed5 --- /dev/null +++ b/media/src/components/APIPage/API.module.css @@ -0,0 +1,76 @@ +.pontx-ui-api { + min-width: 540px; + overflow: auto; + .web-debug{ + margin: 12px 40px 12px; + float:right + } + .debug-comp-content{ + display: flex; + flex-direction: row; + } + .debug-comp-content-column { + flex-direction: column; + } + .left-panel { + .head-content{ + padding: 20px; + border-bottom: 1px #ccc solid; + } + .middle-content{ + /* border: 1px #ccc solid; + border-top: 0px; */ + padding: 20px; + height: calc(100vh - 370px); + overflow: auto; + } + .footer-content{ + padding: 20px; + border-top: 1px #ccc solid; + display: flex; + justify-content: space-between; + } + + } + .left-panel-column { + overflow: auto; + border: #ccc 1px solid; + .middle-content{ + /* border: 1px #ccc solid; + border-top: 0px; */ + padding: 20px; + height: 200px; + overflow: auto; + } + } + .right-panel { + min-width: 540px; + border-left: 1px #ccc solid; + .right-ops{ + padding: 0 16px; + font-weight: 500; + } + .content{ + padding: 0 0 16px 20px; + height: calc(100vh - 270px); + overflow: auto; + .api-params-doc{ + overflow: auto; + } + .semix-schema-table{ + table-layout: fixed; + .param-name { + width: 280px; + } + .param-name div > div{ + display: flex; + flex-wrap: wrap; + } + } + /* .param-name.semix-table-td{ + max-width: 280px; + } */ + } + } +} + diff --git a/media/src/components/APIPage/API.tsx b/media/src/components/APIPage/API.tsx index 1438de5..48eb700 100644 --- a/media/src/components/APIPage/API.tsx +++ b/media/src/components/APIPage/API.tsx @@ -16,6 +16,13 @@ import { APIPageContext } from "./context"; import APIDebugger from "./APIDebugger/APIDebugger"; import { SemixForm } from "../SemixFormRender"; import { TryAPI } from "./TryAPI/TryAPI"; +import TrySDK from "./TrySDK/TrySDK"; +import { Dropdown, MenuProps } from "antd"; +import { PontUIService } from "../../service/UIService"; +import { getVSCode } from "../../utils/utils"; +import { SemixJsonSchema } from "semix-core"; +import _ from "lodash"; +import { useResizeObserver } from 'react-use-observer'; export class APIProps { selectedApi?: PontSpec.PontAPI; @@ -30,6 +37,7 @@ export class APIProps { export const API: React.FC = (props) => { const { selectedApi, definitions } = props; + const [mode, changeMode] = React.useState("doc" as any); const getSchema = React.useCallback( ($ref: any) => { @@ -73,10 +81,29 @@ export const API: React.FC = (props) => { }; }, [definitions, getSchema]); + const mapSchema = (schema) => { + + return SemixJsonSchema.mapSchema(schema as any, (schema)=>{ + if(schema?.properties){ + Object.keys(schema.properties)?.map((item=>{ + schema.properties[item] = mapSchema(schema.properties[item]) + })) + } + if(schema?.$ref){ + schema = getSchema(schema?.$ref) + schema = mapSchema(schema) + return schema; + } + return schema + }) + }; + const pathEle = selectedApi?.path ?
{selectedApi.path}
: null; const apiNameEle = selectedApi?.name ?
{selectedApi?.name}
: null; - const paramsSchema = selectedApi?.parameters?.reduce( + let paramsSchema = _.cloneDeep(selectedApi?.parameters) + const newParamsSchema = paramsSchema?.reduce( (result, param) => { + param.schema = mapSchema(param.schema); return { ...result, properties: { @@ -91,16 +118,117 @@ export const API: React.FC = (props) => { const form = SemixForm.useForm({ formData: {}, // eslint-disable-next-line @typescript-eslint/no-explicit-any - schema: paramsSchema as any, + schema: newParamsSchema as any, context: {}, getCustomWidget: getCustomWidget, }); + const tabs = [ + { tab: "文档", key: "doc" }, + { tab: "调试", key: "debug" }, + { tab: "代码示例", key: "sdk" }, + ]; + + const [pageEl, resizeObserverEntry] = useResizeObserver(); + + const [boxWidth, setBoxWidth] = React.useState(0); + React.useEffect(() => { + const { width = 0, height = 0 } = resizeObserverEntry?.contentRect || {}; + if (width !== boxWidth) { + setBoxWidth(width); + } + }, [boxWidth, resizeObserverEntry]); + + const renderContent = React.useMemo(() => { + const documentComp = ( +
+ {selectedApi?.description ? ( +
+ +
+ ) : null} +
+
入参
+ +
+
+
出参
+ { + return ( + + + 无出参定义 + + + ); + }} + /> +
+ {props.renderMore?.()} +
+ ); + const debugComp = ( +
+
+ +
+
+ { + changeMode(key); + }} + > + + {documentComp} + + +
+ +
+
+ +
+ +
+
+
+
+
+ ); + switch (mode) { + case "doc": + return documentComp; + case "debug": + return debugComp; + case "sdk": + return debugComp; + default: + return debugComp; + } + }, [mode, boxWidth]); + return ( -
+
{/* */} {selectedApi ? ( @@ -109,7 +237,6 @@ export const API: React.FC = (props) => {
{selectedApi.method ?
{selectedApi.method?.toUpperCase()}
: null} - {selectedApi.deprecated ? ( deprecated @@ -120,20 +247,11 @@ export const API: React.FC = (props) => {
{pathEle ? apiNameEle : null} - {selectedApi?.externalDocs ? ( - - ) : null} + changeMode(val)}> + {tabs.map((tab) => ( + + ))} +
{selectedApi?.summary ? ( @@ -144,62 +262,7 @@ export const API: React.FC = (props) => {
) : null}
-
- {/*
- -
*/} -
- - -
- {selectedApi?.description ? ( -
- -
- ) : null} -
-
入参
- -
-
-
出参
- { - return ( - - - 无出参定义 - - - ); - }} - /> -
- {props.renderMore?.()} -
-
- -
敬请期待...
-
- -
敬请期待...
- {/*
*/} -
-
-
-
+
{renderContent}
) : null} diff --git a/media/src/components/APIPage/APIDebugger/APIDebugger.module.scss b/media/src/components/APIPage/APIDebugger/APIDebugger.module.scss new file mode 100644 index 0000000..5d36800 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/APIDebugger.module.scss @@ -0,0 +1,31 @@ +.semix-form-field{ + margin: 8px 0; + .codicon{ + vertical-align: middle; + position: relative; + bottom: 2px; + } +} +.alicloud-schema-form-object, +.alicloud-schema-form-list { + position: relative; + + .child-list { + padding-left: 12px; + } + + &::before { + content: ""; + display: block; + width: 3px; + height: 100%; + background-color: #ddd; + position: absolute; + top: 0; + bottom: 0; + left: 0; + } +} +.endpoint-selector-title{ + margin: 8px 0; +} \ No newline at end of file diff --git a/media/src/components/APIPage/APIDebugger/APIDebugger.tsx b/media/src/components/APIPage/APIDebugger/APIDebugger.tsx index c9fea4d..7d55526 100644 --- a/media/src/components/APIPage/APIDebugger/APIDebugger.tsx +++ b/media/src/components/APIPage/APIDebugger/APIDebugger.tsx @@ -1,46 +1,70 @@ /** - * @author nianyi - * @description API调试器 + * @author yini-chen + * @description API debugger */ import React from "react"; import { APIPageContext } from "../context"; import { Input, Button } from "@alicloud/console-components"; import { SemixForm } from "../../SemixFormRender"; +import I18N from "../../../utils/I18N"; +import { PontUIService } from "../../../service/UIService"; +import { endpointsMocks } from "../../../mocks/endpoints"; +import RegionSelector from "./RegionSelector"; +import { xconsoleWidgets } from "./widgets/xconsole"; +import { APIGuide } from "./APIGuide"; +// import { APIGuide } from "./Guide"; +// import { APIGuide } from "./APIGuide"; +// import APIGuide from "./Guide"; export class APIDebuggerProps {} export const APIDebugger: React.FC = (props) => { - const { apiMeta, schemaForm, product, version, onDebug } = APIPageContext.useContainer(); + const { apiMeta, schemaForm, product, version, onDebug, changeMode, endpoints, regionId, setRegionId } = APIPageContext.useContainer(); - return React.useMemo(() => { - return ( -
- {apiMeta.title} - { - // callVscode({ data: value, type: "openAPIDebug", requestId: 100 }, (res) => { - // console.log("callVscode callback", res); - // }); - // }} - > - + const endpoint = regionId ? endpoints?.find((item) => item.regionId === regionId)?.public : endpoints?.find((item) => item.regionId === 'cn-hangzhou')?.public; + + return ( +
+
+
- ); - }, [schemaForm.formData]); +
+ { + return + }} + form={schemaForm as any} + // onChange={(value): void => { + // callVscode({ data: value, type: "openAPIDebug", requestId: 100 }, (res) => { + // console.log("callVscode callback", res); + // }); + // }} + > +
+
+ +
+ +
+ ); }; APIDebugger.defaultProps = new APIDebuggerProps(); export default APIDebugger; diff --git a/media/src/components/APIPage/APIDebugger/APIGuide.module.scss b/media/src/components/APIPage/APIDebugger/APIGuide.module.scss new file mode 100644 index 0000000..cab44bf --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/APIGuide.module.scss @@ -0,0 +1,44 @@ +.api-debugger-guide-wrapper { + .guide { + display: flex; + .must { + line-height: 22px; + vertical-align: middle; + + &:before { + display: inline-block; + margin-right: 8px; + color: red; + line-height: 22px; + content: '*'; + } + } + .name { + margin-right: 4px; + // margin-right: 8px; + color: #333333; + font-weight: 500; + font-size: 12px; + font-family: Alibaba-PuHuiTi; + line-height: 22px; + vertical-align: 0; + } + .desc { + display: inline-block; + max-width: 290px; + margin-right: 4px; + overflow: hidden; + color: #787878; + font-size: 12px; + line-height: 24px; + white-space: nowrap; + text-overflow: ellipsis; + vertical-align: middle; + vertical-align: -0.6em; + cursor: pointer; + } + .api-debugger-param-desc { + color: #787878; + } + } +} \ No newline at end of file diff --git a/media/src/components/APIPage/APIDebugger/APIGuide.tsx b/media/src/components/APIPage/APIDebugger/APIGuide.tsx new file mode 100644 index 0000000..aa94a18 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/APIGuide.tsx @@ -0,0 +1,183 @@ +/** + * @author yini-chen + * @description 参数Title + */ +import { Balloon, Icon, Tag } from "@alicloud/console-components"; +import React from "react"; +import { SemixMarkdown } from "semix-schema-table"; + +export class APIGuideProps { + schema?: any; + isRequired?: boolean; + fieldName?: string; + dataPath?: string; + collapsed?: boolean; + setCollapsed?: (collapsed: boolean) => void; + deleteHeader?: Function; + changeValue?: (dataPath: string, value: string | number | boolean) => void; + // titleOperator?: any; + product: string; + version: string; +} + +export const APIGuide = React.memo((props: APIGuideProps) => { + + const description = props.schema?.description || props.schema?.title; + + const getShortName = (des: string) => { + const endIndex = Math.min( + ...[",", "\n", "。"].map((ch) => des.indexOf(ch)).map((num) => (num === -1 ? Number.MAX_VALUE : num)), + ); + let shortName = des; + + if (endIndex !== -1) { + shortName = des.slice(0, endIndex); + } + + if (shortName.startsWith("/g) || []; + repalceStrs?.map((str) => { + shortName = shortName.replace(str, ""); + }); + } + + if (shortName.length > 19) { + return `${shortName.slice(0, 16)}...`; + } + return shortName; + }; + const shortDesc = /[0-9]+$/.test(props.fieldName) ? "" : getShortName(description || ""); + + let hasCollapsedIcon = ["object", "array"].includes(props.schema.type as any); + if (props.schema?.type === "array" && ["string", "number", "integer"].includes(props.schema?.items?.type as any)) { + hasCollapsedIcon = false; + } + + const hasHelpTip = !!( + description?.length > shortDesc.length || + props.schema?.example || + props.schema?.maximum || + props.schema?.minimum || + props.schema?.enum?.length || + props.schema?.pattern || + props.schema?.format + ); + + const paramTitle = /[0-9]+$/.test(props.fieldName) + ? props.fieldName.substring(props.fieldName.lastIndexOf(".") + 1, props.fieldName.length) + : props.fieldName; + + if (!paramTitle?.length) { + return null; + } + + return ( +
+ {!props.schema?.isRoot ? ( +
+ {hasCollapsedIcon ? ( +
{ + props.setCollapsed(!props.collapsed); + }} + style={{ marginRight: 8, paddingTop: 2 }} + > + {props.collapsed ? ( +
+ ) : ( +
+ )} +
+ ) : null} +
+
+ {props.isRequired ? : null} + {paramTitle} + + {hasHelpTip && shortDesc?.length ? ( + + {shortDesc} + +
+
+ } + > +
+ 描述 +
+ +
+ {props.schema?.example ? ( + <> +
+ 示例值 +
+ +
{props.schema?.example}
+ + ) : null} + {props.schema?.maximum ? ( + <> +
最大值
+
{props.schema?.maximum}
+ + ) : null} + {props.schema?.minimum ? ( + <> +
最小值
+
{props.schema?.minimum}
+ + ) : null} + {props.schema?.format ? ( + <> +
格式
+
{props.schema?.format}
+ + ) : null} + {props.schema?.enum?.length ? ( + <> +
枚举值
+ {props.schema?.enum?.map((item) => ( + + {item.value || item} + + ))} + + ) : null} + {props.schema?.pattern ? ( + <> +
正则
+
{props.schema?.pattern}
+ + ) : null} +
+ +
+ ) : null} + +
+
+ {/* {isNewHeader && props.deleteHeader ? ( + + { + props.deleteHeader(props.schema); + }} + /> + + ) : null} */} +
+ ) : null} +
+ ); +}); diff --git a/media/src/components/APIPage/APIDebugger/RegionSelector.tsx b/media/src/components/APIPage/APIDebugger/RegionSelector.tsx new file mode 100644 index 0000000..2d7b936 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/RegionSelector.tsx @@ -0,0 +1,53 @@ +/** +* @author yini-chen +* @description +*/ +import React from 'react' +import { Select } from "@alicloud/console-components"; +import _ from "lodash"; +import I18N from '../../../utils/I18N'; + +export class RegionSelectorProps { + regionId: string; + setRegionId: (endpoint: string) => void; + product: string; + endpoints: any[]; +} + +export const RegionSelector: React.FC = (props) => { + + const dataSource = React.useMemo(() => { + if (props.endpoints.length) { + const areaGroups = _.groupBy(props.endpoints, "areaId"); + const areaGroupsOrder = ["asiaPacific", "europeAmerica", "middleEast", "industryCloud"]; + return areaGroupsOrder?.map((area) => { + return { + label: areaGroups[area]?.[0]?.areaName, + children: areaGroups[area]?.map((endpoint) => { + return { + label: endpoint.regionName, + key: endpoint.regionId, + value: endpoint.regionId, + }; + }), + }; + }); + } + return [] + }, [props.endpoints]); + + return ( +
+
{I18N.main.explorer.endPoint}
+ +
+ ); + +} +RegionSelector.defaultProps = new RegionSelectorProps(); +export default RegionSelector; \ No newline at end of file diff --git a/media/src/components/APIPage/APIDebugger/utils.ts b/media/src/components/APIPage/APIDebugger/utils.ts index 861dd01..3faf23a 100644 --- a/media/src/components/APIPage/APIDebugger/utils.ts +++ b/media/src/components/APIPage/APIDebugger/utils.ts @@ -1,35 +1,34 @@ -import _ from "lodash"; -import { SemixUISchema } from "../../SemixFormRender"; - -export const getCustomWidget = (schema: SemixUISchema): string => { - if (schema?.customWidget === 'conditionInfo') { - return 'conditionInfo'; +export const getCustomWidget = (schema): string => { + if (schema?.type === 'array') { + // if (schema.items?.type === 'string' && schema?.widget === 'stringList') { + // return 'stringList'; + // } + return 'list'; + } + if (schema?.type === 'string') { + if (schema?.isFileTransferUrl) { + return 'fileTypeSelect'; } - if (schema?.type === 'array') { - if (schema.items?.type === 'string' && schema?.widget === 'stringList') { - return 'stringList'; - } - return 'list'; + if (schema?.format === 'binary') { + return 'file'; } - - if (schema?.type === 'string') { - if (schema?.format === 'binary') { - return 'binary'; - } - if (schema?.enumValueTitles && Object.keys(schema?.enumValueTitles || {}).length < 5) { - return 'radio'; - } else if (schema?.enum && schema?.enum?.length < 5) { - return 'radio'; - } else if (schema?.enum || schema?.enumValueTitles || schema?.assistSchema?.dynamicEnumConfig) { - return 'enum'; - } - return 'string'; - } else if (schema?.type === 'boolean') { - return 'booleanSwitch'; - } else if (schema?.type === 'object' && !_.isEmpty(schema?.additionalProperties)) { - return 'map'; - } else if (schema?.type === 'object' && !schema?.properties) { - return 'json'; + if (schema?.enum || schema?.enumValueTitles) { + return 'enum'; } - return ''; - }; \ No newline at end of file + return 'string'; + } else if (schema?.type === 'boolean') { + return 'booleanSwitch'; + } else if (schema?.type === 'object' && schema?.additionalProperties) { + return 'map'; + } else if (schema?.type === 'object' && !schema?.properties) { + return 'json'; + } else if (schema?.type === 'any') { + return 'typeSelect'; + } else if ((schema?.ref || schema?.$ref) && !schema?.properties && !schema?.items) { + return 'struct'; + } + // else if (schema?.type === 'number' || (schema?.type === 'integer' && schema?.format === 'int64')){ + // return "string" + // } + return ''; +}; \ No newline at end of file diff --git a/media/src/components/APIPage/APIDebugger/widgets/types.ts b/media/src/components/APIPage/APIDebugger/widgets/types.ts new file mode 100644 index 0000000..608fa8d --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/types.ts @@ -0,0 +1,81 @@ +import { SemixJsonSchema } from "semix-core"; + +export class ErrorField { + dataPath: string; + message: string; +} + +export type AlicloudUISchema = SemixJsonSchema & { + widget?: string; + + disabled?: boolean; + + hidden?: boolean; + + isRoot?: boolean; + + unCheckedChildren?: string; + + checkedChildren?: string; + + mode?: "simple" | "card"; + + labelWidth?: number; + + placeholder?: string; + + /** 是否存在,一般用于条件式存在的表单项 */ + exists?: boolean; + + // properties?: SchemaMap; + properties?: any; + additionalProperties?: AlicloudUISchema; + items?: AlicloudUISchema; + + /** 枚举值为空时,下拉框展示内容,一般用于推荐枚举值为空时引导用户 */ + emptyEnumContent?: any; +}; + +export class CommonWidgetProps { + value: any; + schema = {} as AlicloudUISchema; + onChange(value: any) {} +} + +export class ListProps { + addItem: () => any; + copyItem: (index: number) => any; + deleteItem: (index: number) => any; + errorFields: ErrorField[]; + dataPath: string; + schemaPath: string; + schema: AlicloudUISchema; + displayList: any[]; + fieldName: string; + renderTitle?: Function; +} + +export class MapProps { + editItemKey: (index: number, newKey: string) => any; + addItem: () => any; + copyItem: (index: number) => any; + deleteItem: (index: number) => any; + errorFields: ErrorField[]; + dataPath: string; + schema: AlicloudUISchema; + displayList: any[]; + fieldName: string; + renderTitle?: Function; +} + +export class AnyProps { + handleTypeChange: (type: string) => any; + type: string; + dataPath: string; + schema: AlicloudUISchema; + onChange(value: any) {} + widgets: any; + Icon: any; +} + +export type SimpleTypes = "array" | "boolean" | "integer" | "null" | "number" | "object" | "string"; diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/FileUploadType.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/FileUploadType.tsx new file mode 100644 index 0000000..49c5f74 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/FileUploadType.tsx @@ -0,0 +1,54 @@ +// /** +// * @author yini-chen +// * @description 文件上传方式选择组件 +// */ + +// import React from 'react'; +// import { Switch } from '@alicloud/console-components'; +// import { xconsoleWidgets } from '.'; +// import { CommonWidgetProps } from '../types'; + +// export class FileUploadTypeProps extends CommonWidgetProps { +// dataPath?: string; +// } + +// export const FileUploadType: React.FC = (props) => { +// const { dataPath, schema, onChange } = props; +// const [isFile, changeIsFile] = React.useState(false); +// const curvalue = props.value || ''; + +// const handleTypeChange = React.useCallback((value: boolean) => { +// changeIsFile(value); +// }, []); + +// const getUIType = (isFile: boolean) => { +// if (isFile) return 'file'; +// return 'string'; +// }; +// const getText = (isFIle: boolean) => { +// return isFIle ? '输入URL' : '上传文件'; +// }; +// const UIType = getUIType(isFile); +// const text = getText(isFile); + +// // 变化的参数组件,默认为字符串 +// const ParamUI = React.useMemo(() => { +// return ampWidgets[UIType] || ampWidgets['string']; +// }, [UIType]); + +// return ( +//
+// { +// handleTypeChange(value); +// }} +// /> +// {text} +//
+// +//
+//
+// ); +// }; + +// FileUploadType.defaultProps = new FileUploadTypeProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/JsonEdit.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/JsonEdit.tsx new file mode 100644 index 0000000..fae583c --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/JsonEdit.tsx @@ -0,0 +1,54 @@ +/** + * @author yini-chen + * @description 表单 Json 编辑器 + */ + +import * as React from "react"; +import { CommonWidgetProps } from "../types"; +import { Editor } from "@monaco-editor/react"; + +export class JsonEditProps extends CommonWidgetProps {} + +export const JsonEdit: React.FC = (props) => { + const [curval, setCurval] = React.useState(""); + const [errMsg, setErrMsg] = React.useState(""); + React.useEffect(() => { + setErrMsg(""); + if (typeof props.value !== "string") { + try { + const obj = JSON.stringify(props.value, null, 2); + setCurval(obj); + } catch {} + } + }, [props.value]); + + return ( +
{ + try { + const val = JSON.parse(curval); + props.onChange(val); + } catch { + setErrMsg("json 格式错误"); + } + }} + > +
{ + setCurval(value); + }} + options={{minimap:{ + enabled:false + }}} + >
+ {errMsg?.length ?
{errMsg}
: null} +
+ ); +}; + +JsonEdit.defaultProps = new JsonEditProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/Object.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/Object.tsx new file mode 100644 index 0000000..808fc3c --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/Object.tsx @@ -0,0 +1,111 @@ +/** + * @author yini-chen + * @description object,object回填value可能为string + */ +import * as _ from 'lodash'; +import * as React from 'react'; +import { AlicloudUISchema } from '../types'; +import { FormStoreContext } from '../../../../SemixFormRender/context'; +import { Field } from '../../../../SemixFormRender/common/Field'; +import { getNextDataPath } from '../../../../SemixFormRender/utils'; +import { getNextSchemaPath } from './utils'; + +export class RenderObjectProps { + schema: AlicloudUISchema; + dataPath: string; + schemaPath: string; + value: any; + onChange: (value: any) => void; +} + +export const RenderObject: React.FC = (props) => { + if (props.value && typeof props.value === 'string') { + let value = {}; + try { + const tmpValue = JSON.parse(props.value); + if (typeof tmpValue === 'object') { + value = tmpValue; + } + } catch {} + props.onChange(value); + } + const [groupCollapsed, setGroupCollapsed] = React.useState({} as { [x: string]: boolean }); + const store = FormStoreContext.useContainer(); + + return React.useMemo(() => { + if (props.schema?.properties) { + const propItems = Object.keys((props.schema?.properties as any) || {}).map((key) => { + return { key, schema: props.schema?.properties[key] }; + }); + const propItemsGroups = _.groupBy(propItems, (item) => { + return item.schema?.group || ''; + }); + const renderField = (key: string) => { + return ( + + ); + }; + const noGroupPropItems = (propItemsGroups?.[''] || []).map((item) => { + return renderField(item?.key); + }); + const groups = _.map(propItemsGroups, (items, groupKey) => { + if (groupKey) { + const titleProps = { + key: groupKey, + index: items?.[0]?.schema?.groupIndex, + collapsed: groupCollapsed[groupKey], + setCollapsed: (newCollapsed: boolean) => + setGroupCollapsed((boolMap) => { + return { + ...boolMap, + [groupKey]: newCollapsed, + }; + }), + }; + const title = store.renderGroupArea?.(titleProps) ||
{groupKey}
; + + return { + dom: ( +
+ {title} + {groupCollapsed[groupKey] ? null : ( +
{(items || []).map((item) => renderField(item?.key))}
+ )} +
+ ), + index: items?.[0]?.schema?.groupIndex, + }; + } + return null; + }).filter((id) => id); + + const result = [ + ...groups, + { + dom: noGroupPropItems, + index: 0, + }, + ] + .sort((pre, next) => pre.index - next.index) + .map((item) => { + return item.dom; + }); + + return ( +
+
{result}
+
+ ); + } + return null; + }, [groupCollapsed, props.schema, props.dataPath]); +}; + +RenderObject.defaultProps = new RenderObjectProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/RenderMap.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/RenderMap.tsx new file mode 100644 index 0000000..632373b --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/RenderMap.tsx @@ -0,0 +1,121 @@ +/** + * @author yini-chen + * @description Map + */ +import * as React from "react"; +import * as _ from "lodash"; +import { AlicloudUISchema, ErrorField, MapProps } from "../types"; +import { FormStoreContext } from "../../../../SemixFormRender/context"; + +export class RenderMapProps { + dataPath = ""; + schema = {} as AlicloudUISchema; + errorFields = [] as ErrorField[]; + fieldName: string; + renderTitle?: Function; +} + +export const RenderMap: React.FC = (props) => { + const { formData, onItemChange, widgets, errorFields } = FormStoreContext.useContainer(); + + const typeOfValue = props?.schema?.additionalProperties?.type || 'string' + + const InitValue = { + string: "", + number: 0, + object: {}, + array: [], + boolean: false, + integer: 0, + map: {}, + $ref: {}, + any:"" + } + + const MapUI = widgets["simpleMap"]; + + const [mapData, setMapData] = React.useState({ "": InitValue[typeOfValue] || "" } as { [key: string]: any }); + const [displayList, setDisplayList] = React.useState([{ key: "", value: InitValue[typeOfValue] || "" } as { key: string; value: any }]); + + React.useEffect(() => { + if (_.get(formData, props.dataPath) !== mapData) { + setMapData(_.get(formData, props.dataPath)); + } + }, [_.get(formData, props.dataPath)]); + + React.useEffect(() => { + const uiList = + typeof mapData === "object" && Object.keys(mapData).length + ? Object.keys(mapData).map((key) => { + return { key, value: mapData[key] }; + }) + : [{ key: "", value: "" as any } as { key: string; value: any }]; + if (!_.isEqual(uiList, displayList)) { + setDisplayList(uiList); + } + }, [mapData]); + + const addItem = () => { + const newItem = InitValue[typeOfValue] || ""; + const newList = [...displayList, { key: "", value: newItem }]; + setDisplayList([...newList]); + const newIndex = newList.length - 1; + return newIndex; + }; + + const copyItem = (index: number) => { + const newItem = { + key: displayList[index].key + "-copy", + value: displayList[index].value, + }; + const newList = [...displayList.slice(0, index), newItem, ...displayList.slice(index)]; + setDisplayList([...newList]); + }; + + const editItemKey = (index: number, newKey: string) => { + const tempList = displayList; + tempList[index].key = newKey; + setDisplayList([...tempList]); + calculateValue(); + }; + + const calculateValue = React.useCallback(() => { + const resultValue = {} as { [key: string]: any }; + displayList.map((item) => { + resultValue[item.key] = item.value; + }); + onItemChange(props.dataPath, resultValue); + setMapData(resultValue); + }, [displayList]); + + const deleteItem = (index: number) => { + // 删除元素的时候,也需要delete相对于的校验信息(errorFields) + const newErrors = errorFields.filter((error) => { + return error.dataPath !== props.dataPath + "." + displayList[index].key; + }); + // setErrorFields(newErrors); + const newList = displayList.filter((item, kdx) => kdx !== index); + setDisplayList(newList); + }; + + React.useEffect(() => { + calculateValue(); + }, [displayList]); + + const mapProps = { + editItemKey, + addItem, + copyItem, + deleteItem, + errorFields: props.errorFields, + dataPath: props.dataPath, + schema: props.schema?.additionalProperties, + displayList, + fieldName: props.fieldName, + renderTitle: props.renderTitle || null, + } as MapProps; + + return ; +}; + +RenderMap.defaultProps = new RenderMapProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/Struct.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/Struct.tsx new file mode 100644 index 0000000..8a8118a --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/Struct.tsx @@ -0,0 +1,46 @@ +/** + * @author yini-chen + * @description 数据结构 + */ +// import { AmpIcon } from '@ali/amp-base'; +// import { CommonWidgetProps } from '@ali/api-component'; +// import { LinkButton } from '@alicloud/console-components-actions'; +import React from 'react'; +import { CommonWidgetProps } from '../types'; +// import { addParamStruct } from './utils'; +// import { addParamStruct } from '../utils'; + +export class StructProps extends CommonWidgetProps { + onChange: (value: any) => void; + schemaPath: string; +} + +export const Struct: React.FC = (props) => { + if (props.value) { + if (typeof props.value === 'string') { + let value = props.value; + try { + value = JSON.parse(props.value); + } catch {} + props.onChange(value); + } + // addParamStruct(props.schemaPath, props.schema); + } + return ( + + ); +}; + +Struct.defaultProps = new StructProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/UploadFile.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/UploadFile.tsx new file mode 100644 index 0000000..1fcaeb2 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/UploadFile.tsx @@ -0,0 +1,77 @@ +/** + * @author yini-chen + * @description 上传文件 + */ + +import { Button, message, Upload } from 'antd'; +import { UploadOutlined } from '@ant-design/icons'; +import * as React from 'react'; +import { CommonWidgetProps } from '../types'; +import { APIPageContext } from '../../../context'; +// import { CommonWidgetProps } from '@ali/api-component'; +// import { useLocation } from 'react-router-dom'; + +export class UploadFileProps extends CommonWidgetProps { + onChange: (value: any) => void; +} + +export const UploadFile: React.FC = (props) => { + const [isUpload, changeIsUpload] = React.useState(false); + const { apiMeta } = APIPageContext.useContainer(); +// const location = useLocation(); +// const [product, version, apiName] = location?.pathname?.replace('/api/', '').split('/'); + const [fileInfo, setFileInfo] = React.useState({ fileName: '', mime: '' } as FileInfo); + + type FileInfo = { + fileName: string; + mime: string; + }; + + const getUploadPath = (product: string, version: string, apiName: string, fileInfo: FileInfo) => { + let path = `/api/auth/product/oss/file`; + if (props.schema?.isFileTransferUrl) { + path = `/api/auth/product/oss/file?product=${product}&apiName=${apiName}&apiVersion=${version}&name=${fileInfo.fileName}&mime=${fileInfo.mime}`; + } + return path; + }; + + return ( +
暂不支持文件传输调试,您可以到开发者门户网页版进行调试
+ // { + // if (val?.file?.status === 'done') { + // props.onChange(val?.file?.response?.tmpId || ''); + // } + // }} + // onRemove={() => { + // changeIsUpload(false); + // props.onChange(''); + // }} + // maxCount={1} + // beforeUpload={(file) => { + // console.log(file) + // if (file.size > 52428800) { + // message.error('暂不支持上传超过50M的文件哦!'); + // return Upload.LIST_IGNORE; + // } + // const nameArr = file?.name?.split('.'); + // const mime = Array.isArray(nameArr) ? nameArr[nameArr.length - 1] : ''; + // const fileName = file?.name?.replace('.' + mime, ''); + // setFileInfo({ fileName: fileName, mime: mime }); + // return true; + // }} + // > + // + // + ); +}; + +UploadFile.defaultProps = new UploadFileProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/any.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/any.tsx new file mode 100644 index 0000000..d505a87 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/any.tsx @@ -0,0 +1,84 @@ +/** + * @author yini-chen + * @description any类型 + */ + +import * as React from "react"; +import _ from "lodash"; +import { Select } from "@alicloud/console-components"; +import { Tooltip } from "antd"; +import { xconsoleWidgets } from "."; +import { getTypeOfValue, simpleType } from "./utils"; +import { AnyProps } from "../types"; + + +export class TypeSelectorProps extends AnyProps { + value: any; +} + +export const TypeSelector: React.FC = (props) => { + const { dataPath, onChange, schema, Icon, value } = props; + + const [type, handleTypeChange] = React.useState(value !== undefined ? getTypeOfValue(value) : "string" as any); + + React.useEffect(() => { + props.onChange(undefined); + schema.type = type + }, [type]); + + + const getUIType = (type: string) => { + if (type === "boolean") return "booleanSwitch"; + if (type === "array") return "json"; + if (type === "object") return "json"; + return type; + }; + const UIType = getUIType(type); + + // 变化的参数组件,默认为字符串 + const ParamUI = React.useMemo(() => { + return xconsoleWidgets[UIType] || xconsoleWidgets["string"]; + }, [UIType]); + + // 可选择的数据类型 + const renderTypes = React.useMemo(() => { + const typeList = simpleType; + return typeList.map((item) => { + return ( + + {item} + + ); + }); + }, []); + + return ( +
+ 参数类型 + {Icon ? ( + + + + + + ) : null} + : + +
+ +
+
+ ); +}; + +TypeSelector.defaultProps = new TypeSelectorProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/base/List.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/base/List.tsx new file mode 100644 index 0000000..94dc3b1 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/base/List.tsx @@ -0,0 +1,118 @@ +/** + * @author + * @description 列表 + */ +import * as _ from 'lodash'; +import * as React from 'react'; +import { SemixJsonSchema } from 'semix-core'; +import { ErrorField } from '../../types'; +import { FormStoreContext } from '../../../../../SemixFormRender/context'; +import { ListProps } from '../../../../../SemixFormRender'; +// import { FormStoreContext, ListProps } from 'semix-form-render'; + +export class RenderListProps { + dataPath = ''; + schema = {} as SemixJsonSchema; + errorFields = [] as ErrorField[]; + fieldName: string; + renderTitle?: (props) => void; + schemaPath? = ''; +} + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +function getSchemaDefaultValue(schema: SemixJsonSchema) { + switch (schema.type) { + case 'object': { + // if (schema.properties) { + // return mapObject(schema.properties, (property: SemixJsonSchema, key) => { + // return getSchemaDefaultValue(property); + // }); + // } + + return {}; + } + case 'array': { + // if (schema.items) { + // return []; + // } + return []; + } + } + + return undefined; +} + +export const RenderList: React.FC = (props) => { + const { formData, onItemChange, widgets, errorFields } = FormStoreContext.useContainer(); + + const customWidget = props.schema?.customWidget || 'simpleList'; + + const ListUI = widgets[customWidget] || widgets['simpleList']; + + let listData = _.get(formData, props.dataPath); + const displayList = Array.isArray(listData) && listData.length ? listData : [""]; + + const addItem = (): number => { + const newItem = props.schema.items ? getSchemaDefaultValue(props.schema.items) || '' : ''; + const newList = [...displayList, newItem]; + const newIndex = newList.length - 1; + onItemChange(props.dataPath, newList); + return newIndex; + }; + + const changeItemValue = (value, index): void => { + let newList = [...displayList]; + if (index === displayList?.length) { + newList.push(value); + } else { + newList[index] = value; + } + onItemChange(props.dataPath, newList); + }; + + const copyItem = (index: number): void => { + const newItem = displayList[index]; + const newList = [...displayList.slice(0, index), newItem, ...displayList.slice(index)]; + onItemChange(props.dataPath, newList); + }; + + const deleteItem = (index: number): void => { + // 删除元素的时候,也需要delete相对于的校验信息(errorFields) + const newErrors = errorFields.filter((error) => { + return !error.dataPath.includes(props.dataPath + '.' + index); + }); + // setErrorFields(newErrors); + const newList = displayList.filter((item, kdx) => kdx !== index); + onItemChange(props.dataPath, newList); + }; + + const listProps = { + addItem, + copyItem, + deleteItem, + errorFields: props.errorFields, + dataPath: props.dataPath, + schemaPath: props.schemaPath, + schema: props.schema?.items, + displayList, + fieldName: props.fieldName, + renderTitle: props.renderTitle || null, + parentSchema: props.schema, + /** + * 根据index改变对应值 + */ + changeItemValue, + /** + * 改变当前dataPath的值 + */ + onChange: onItemChange, + formData: formData || {}, + } as unknown as ListProps; + // return <>ddd; + + return ; +}; + +RenderList.defaultProps = new RenderListProps(); + +export default RenderList; diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/enum.module.scss b/media/src/components/APIPage/APIDebugger/widgets/xconsole/enum.module.scss new file mode 100644 index 0000000..688a544 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/enum.module.scss @@ -0,0 +1,24 @@ +.workbench-enum-item { + position: relative; + &:hover .input-emptystring-button { + display: block; + } + .input-emptystring-button { + position: absolute; + bottom: 16px; + left: 160px; + left: 156px; + z-index: 99; + display: none; + font-size: 12px; + } + .clear-emptystring-button { + position: absolute; + bottom: 16px; + left: 160px; + left: 156px; + z-index: 99; + display: block; + font-size: 12px; + } +} diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/enum.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/enum.tsx new file mode 100644 index 0000000..8a8c5ff --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/enum.tsx @@ -0,0 +1,91 @@ +/** + * @author yini-chen + * @description 枚举选择 + */ + +// import { CommonWidgetProps } from '@ali/api-component'; +import { Select } from '@alicloud/console-components'; +import * as React from 'react'; +import './enum.module.scss'; +import { CommonWidgetProps } from '../types'; + +export class EnumSelectProps extends CommonWidgetProps {} + +export const EnumSelect: React.FC = (props) => { + const { schema, ...rest } = props; + + const [curvalue, setCurvalue] = React.useState(undefined); + + let enumValueTitles = schema?.enum ? [...schema?.enum] : []; + if (schema?.enumValueTitles) { + Object.keys(schema?.enumValueTitles)?.map((key) => { + if (schema?.enum?.includes(key) && enumValueTitles.indexOf(key) !== -1) { + enumValueTitles.splice(enumValueTitles.indexOf(key), 1); + } + enumValueTitles = [ + ...enumValueTitles, + { + value: key, + title: schema?.enumValueTitles[key], + }, + ]; + }); + } + const options = enumValueTitles?.map((item: any) => { + if (item.value === '') { + return; + } + return { + label: ( +
+ {item.value ? item.value : item} + {item.title} +
+ ), + value: item.value ? item.value : item, + key: item.value ? item.value : item, + }; + }); + + const changeCurValue = React.useCallback((value) => { + if (value) { + setCurvalue(value); + } else { + props.onChange(undefined); + setCurvalue(undefined); + } + }, []); + + const emitvalues = React.useCallback(() => { + if (props.value === curvalue) { + return; + } + props.onChange(curvalue); + }, [curvalue]); + + React.useEffect(() => { + setCurvalue(props.value); + }, [props.value]); + + return ( +
+ {/* onGetRandomValue(props.onChange, props.schema)} + changeValue={changeCurValue} + param={props.schema as any}> */} + + {/* */} +
+ ); +}; + +EnumSelect.defaultProps = new EnumSelectProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/index.module.scss b/media/src/components/APIPage/APIDebugger/widgets/xconsole/index.module.scss new file mode 100644 index 0000000..5d724ca --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/index.module.scss @@ -0,0 +1,14 @@ +.workbench-complex-type-item { + .item-treenode-style { + margin-left: -23px; + } + .array-delete-icon { + margin: 0 5px; + } + .op { + margin-right: 8px; + } + .editor-content{ + border: 1px #ccc solid; + } +} \ No newline at end of file diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/index.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/index.tsx new file mode 100644 index 0000000..1886ac7 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/index.tsx @@ -0,0 +1,42 @@ +/** + * @description 门户组件 + * 1、用于api-design-form + * 2、用于api-debugger + */ + +import "./index.module.scss"; +import { String } from "./string"; +import { BooleanSwitch } from "./swtich"; +import { NumberInput } from "./number"; +import { SimpleList } from "./list"; +import { UploadFile } from "./UploadFile"; +import { EnumSelect } from "./enum"; +import { SimpleMap } from "./map"; +import { TypeSelector } from "./any"; +// import { JsonEdit } from "./JsonEdit"; +// import { FileUploadType } from "./FileUploadType"; +import { Struct } from "./Struct"; +import { RenderObject } from "./Object"; +import { RenderMap } from "./RenderMap"; +import RenderList from "./base/List"; +import { JsonEdit } from "./JsonEdit"; + +export const xconsoleWidgets = { + object: RenderObject, + map: RenderMap, + string: String, + booleanSwitch: BooleanSwitch, + number: NumberInput, + integer: NumberInput, + list: RenderList, + // binary: UploadFile, // 文件上传,暂时不支持 + enum: EnumSelect, + simpleMap: SimpleMap, + typeSelect: TypeSelector, // any类型支持选择各种类型 + simpleList: SimpleList, + // list: SimpleList, + file: UploadFile, // 文件上传,暂时不支持 + json: JsonEdit, + // fileTypeSelect: FileUploadType, // 文件上传切换,amp暂时不支持 + struct: Struct, // 数据结构 +}; diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/list.module.scss b/media/src/components/APIPage/APIDebugger/widgets/xconsole/list.module.scss new file mode 100644 index 0000000..2434196 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/list.module.scss @@ -0,0 +1,26 @@ +.alicloud-schema-form-list { + .list-item { + position: relative; + padding: 5px; + .title-operator { + position: absolute; + top: 14px; + right: 0; + z-index: 999; + } + + .op { + margin-right: 8px; + text-decoration: none; + } + .key-item { + background-color: aqua; + .right-outlined { + display: none !important; + } + } + } + // .list-item:hover { + // background-color: #f7f7f7; + // } +} diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/list.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/list.tsx new file mode 100644 index 0000000..0457f45 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/list.tsx @@ -0,0 +1,72 @@ +/** + * @author 奇阳 + * @description + */ +// import { AmpIcon } from '@ali/amp-base'; +// import { LinkButton } from '@alicloud/console-components-actions'; +import * as React from 'react'; +import './list.module.scss'; +import { ListProps } from '../types'; +import { Field } from '../../../../SemixFormRender/common/Field'; +import { Button } from '@alicloud/console-components'; + +export class SimpleListProps extends ListProps {} + +export const SimpleList: React.FC = (props) => { + const children = (props.displayList || []).map((value, index) => { + return ( +
+ + +
+ ); + }); + return ( + + ); +}; + +SimpleList.defaultProps = new SimpleListProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/map.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/map.tsx new file mode 100644 index 0000000..e80cd58 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/map.tsx @@ -0,0 +1,111 @@ +/** + * @author yini-chen + * @description workbench-map + */ +// import { immutableSet } from '@/utils/utils'; +// import { AmpIcon } from '@ali/amp-base'; +// import { Field, MapProps, getNextDataPath } from '@ali/api-component'; +import { Input } from '@alicloud/console-components'; +// import { LinkButton } from '@alicloud/console-components-actions'; +import * as React from 'react'; +import { getNextDataPath, immutableSet } from '../../../../SemixFormRender/utils'; +import { MapProps } from '../types'; +import { Field } from '../../../../SemixFormRender/common/Field'; + +export class SimpleMapProps extends MapProps {} + +export const SimpleMap: React.FC = (props) => { + const [listKeys, changeListKeys] = React.useState((props.displayList || []).map(({ key }) => key)); + + React.useEffect(() => { + changeListKeys((props.displayList || []).map(({ key }) => key)); + }, [props.displayList]); + + const children = React.useMemo(() => { + return (props.displayList || []).map(({ key, value }, index) => { + const keyItem = ( + <> + { + changeListKeys(immutableSet(index, newValue, listKeys) as any); + }} + onBlur={() => { + props.editItemKey(index, listKeys[index]); + }} + /> + + {props.schema?.widget === 'typeSelect' ? null : ( + { + props.copyItem(index); + }} + > + copy + + )} + { + props.deleteItem(index); + }} + > + delete + + + + ); + const valueItem = ( +
+ +
+ ); + + return ( +
+ +
+ {keyItem} + + {' '} + : + +
+
{valueItem}
+
+
+ ); + }); + }, [props.displayList, listKeys]); + return ( + + ); +}; + +SimpleMap.defaultProps = new SimpleMapProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/number.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/number.tsx new file mode 100644 index 0000000..c30202f --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/number.tsx @@ -0,0 +1,78 @@ +/** + * @author yini-chen + * @description 输入数值 + */ +import { NumberPicker } from '@alicloud/console-components'; +import * as React from 'react'; +import { CommonWidgetProps } from '../types'; +// import APIParamGenerate from "viteSrc/pages/designAwesome/APIDesign/QuickTest/APIParams/APIParamGenerate"; + +export class NumberInputProps extends CommonWidgetProps {} + +export const NumberInput: React.FC = (props) => { + const { schema, ...rest } = props; + const [curvalue, setCurvalue] = React.useState(undefined); + + const textMap = { + double: '浮点数值', + float: '浮点数值', + int32: '整型数字', + int64: '整型数字', + } as any; + + // const numberProps = {} as any; + // if (schema.maximum) { + // numberProps.max = schema.maximum; + // } + // if (schema.minimum) { + // numberProps.min = schema.minimum; + // } + + const emitvalues = React.useCallback(() => { + if (props.value === curvalue) { + return; + } + props.onChange(curvalue); + }, [curvalue]); + + const changeCurValue = (value) => { + if (value || value === 0) { + setCurvalue(Number(value)); + } else { + props.onChange(undefined); + setCurvalue(undefined); + } + }; + + React.useEffect(() => { + setCurvalue(props.value); + }, [props.value]); + + const uischema = { + ...props.schema, + type: props.schema?.format?.includes('int') ? 'integer' : props?.schema?.type, + }; + + return ( + // { + // onGetRandomValue(props.onChange, uischema); + // }} + // changeValue={props.onChange} + // param={uischema as any}> + + // + ); +}; + +NumberInput.defaultProps = new NumberInputProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/string.module.scss b/media/src/components/APIPage/APIDebugger/widgets/xconsole/string.module.scss new file mode 100644 index 0000000..b156db5 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/string.module.scss @@ -0,0 +1,60 @@ +.workbench-string-item { + .input-area { + position: relative; + &:hover .input-emptystring-button { + display: block; + } + .input-emptystring-button { + position: absolute; + bottom: -1px; + left: 156px; + z-index: 99; + display: none; + font-size: 12px; + } + .clear-emptystring-button { + position: absolute; + bottom: -1px; + left: 156px; + z-index: 99; + display: block; + font-size: 12px; + } + .close-mini { + margin-right: 6px; + color: #7a7a7a; + } + .close-mini:hover { + background-color: #f7f9fa; + border-radius: 50%; + } + } + .enum-item { + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + .enum-item-title { + margin-left: 10px; + overflow: hidden; + color: #787878; + font-size: 12px; + white-space: nowrap; + text-overflow: ellipsis; + } + } + .generate-form-text-area { + position: relative; + .generate-form-text-area-icon { + position: absolute; + right: 5px; + bottom: 5px; + cursor: pointer; + opacity: 0; + } + &:hover { + .generate-form-text-area-icon { + opacity: 1; + } + } + } +} diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/string.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/string.tsx new file mode 100644 index 0000000..9142eaa --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/string.tsx @@ -0,0 +1,198 @@ +/** + * @author yini-chen + * @description string类型 + */ +// import { SwapOutlined } from '@ant-design/icons'; +import { Tooltip } from 'antd'; + +// import { AmpIcon } from '@ali/amp-base'; +// import { CommonWidgetProps } from '@ali/api-component'; +import { Input } from '@alicloud/console-components'; +import * as React from 'react'; +// import APIParamGenerate from 'viteSrc/pages/designAwesome/APIDesign/QuickTest/APIParams/APIParamGenerate'; +// import APIParamGenerate from '../APIParamGenerate'; +import './string.module.scss'; +import { CommonWidgetProps } from '../types'; +// import { onGetRandomValue } from './utils'; + +export class StringProps extends CommonWidgetProps {} + +export const String: React.FC = (props) => { + const { schema, ...rest } = props; + const [curvalue, setCurvalue] = React.useState(''); + const [isToTextArea, setIsToTextArea] = React.useState(false); + + React.useEffect(() => { + if (props.value !== curvalue) { + if (props.value && typeof props.value !== 'string') { + setCurvalue(props.value + ''); + props.onChange(props.value + ''); + } else { + setCurvalue(props.value); + } + } + }, [props.value]); + + React.useEffect(() => { + if (schema.constant && curvalue !== schema.constant) { + setCurvalue(schema.constant); + } + }, [schema.constant]); + + const ref = React.useRef(); + const textareaRef = React.useRef(); + + const changeCurValue = React.useCallback((val: any) => { + const value = val === '' ? (undefined as any) : val; + if (value) { + setCurvalue(value); + } else { + props.onChange(undefined); + setCurvalue(undefined); + } + }, []); + + const emitvalues = React.useCallback(() => { + if (props.value === curvalue) { + return; + } + props.onChange(curvalue); + }, [curvalue]); + + const getNewTextareaValueAndPosition = (newValue: string) => { + if (!ref || !ref.current || isToTextArea) return { value: newValue, position: newValue.length }; + if (!curvalue) return { value: newValue, position: newValue.length }; + try { + // @ts-ignore + const { selectionStart } = ref.current.input; + const startV = curvalue.substring(0, selectionStart); + const endV = curvalue.substring(selectionStart, curvalue.length); + return { + value: `${startV}${newValue}${endV}`, + position: selectionStart + (newValue?.length || 0), + }; + } catch (error) { + return { value: newValue, position: newValue.length }; + } + }; + + let formItem = null; + let inputType = 'input'; + + if ((isToTextArea || (typeof curvalue === 'string' && curvalue.includes('\n'))) && props.schema?.type !== 'number') { + inputType = 'textarea'; + } + + const placeholder = React.useMemo(() => { + if (curvalue === '') { + return '空字符串'; + } else if (props.schema?.format === 'int64' || props.schema?.format === 'double') { + return '请输入数值'; + } else { + return schema?.placeholder || '请输入字符串'; + } + }, [curvalue, props.schema]); + + const errorMsg = React.useMemo(() => { + if (props.schema?.format === 'int64' || props.schema?.format === 'double') { + return !curvalue || Number(curvalue) || Number(curvalue) === 0 ? null : '请输入数值'; + } + return null; + }, [props.schema, curvalue]); + + switch (inputType) { + case 'textarea': + formItem = ( +
+ + + + { + setCurvalue((curvalue || '').replace(/\n/gi, '')); + setIsToTextArea(false); + }} + > +
+ {/* */} +
+
+
+ ); + break; + default: + case 'input': + formItem = ( +
+ changeCurValue(undefined)} + // > + // ) : null + // } + value={curvalue} + onBlur={emitvalues} + disabled={schema.disabled} + onChange={changeCurValue} + ref={ref} + onPaste={(e) => { + const v = e.clipboardData.getData('text'); + if (typeof v === 'string' && v.includes('\n')) { + setIsToTextArea(true); + e.preventDefault(); + const { value: newValue, position } = getNewTextareaValueAndPosition(v); + setCurvalue(newValue); + Promise.resolve().then(() => { + // @ts-ignore + textareaRef?.current?.resizableTextArea?.textArea?.focus(); + // @ts-ignore + textareaRef?.current?.resizableTextArea?.textArea?.setSelectionRange(position, position); + }); + } + }} + // onKeyDown={(e) => { + // if (e.key === 'Enter') { + // setIsToTextArea(true); + // e.preventDefault(); + // const { value: newValue, position } = getNewTextareaValueAndPosition('\n'); + // setCurvalue(newValue); + // Promise.resolve().then(() => { + // // @ts-ignore + // textareaRef?.current?.resizableTextArea?.textArea?.focus(); + // // @ts-ignore + // textareaRef?.current?.resizableTextArea?.textArea?.setSelectionRange(position, position); + // }); + // } + // }} + > +
+ ); + break; + } + + return ( +
+
{formItem}
+
{errorMsg}
+
+ ); +}; + +String.defaultProps = new StringProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/swtich.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/swtich.tsx new file mode 100644 index 0000000..f2f6ab6 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/swtich.tsx @@ -0,0 +1,36 @@ +/** + * @author yini-chen + * @description Switch + */ +import * as React from 'react'; +// import { CommonWidgetProps } from '@ali/api-component'; +import { Switch } from '@alicloud/console-components'; +import { CommonWidgetProps } from '../types'; + +export class BooleanSwitchProps extends CommonWidgetProps {} + +export const BooleanSwitch: React.FC = (props) => { + const { schema, ...rest } = props; + + let switchDefault = props?.schema?.default; + + if (typeof switchDefault === 'string') { + switchDefault = switchDefault === 'true'; + } + + return ( + { + props.onChange(value); + }} + /> + ); +}; + +BooleanSwitch.defaultProps = new BooleanSwitchProps(); diff --git a/media/src/components/APIPage/APIDebugger/widgets/xconsole/utils.tsx b/media/src/components/APIPage/APIDebugger/widgets/xconsole/utils.tsx new file mode 100644 index 0000000..85e24f4 --- /dev/null +++ b/media/src/components/APIPage/APIDebugger/widgets/xconsole/utils.tsx @@ -0,0 +1,307 @@ +import { Message } from "@alicloud/console-components"; + +export const simpleType: any[] = ["string", "boolean", "number", "array", "object"]; + +// export const onGetRandomValue = async (changeValue, schema) => { +// try { +// const randomValueData: any = await API.apiTest.popFlow.getRandomParameter.request({}, schema); +// if(['number','integer'].includes(schema.type) && schema.format !== "int64"){ +// changeValue(Number(randomValueData.data)); +// } +// else{ +// changeValue(randomValueData.data); +// } +// return randomValueData.data +// } catch (err) { +// Message.error(err?.message); +// return null +// } +// }; + + export const getTypeOfValue = (value)=>{ + if(Array.isArray(value)){ + return 'array'; + } + return typeof value + } + + export const getNextSchemaPath = (schemaPath: any, key: string) => { + const next = key?.includes(".") ? `["${key}"]` : key; + return schemaPath ? schemaPath + ".properties." + next : "properties." + next; + }; + + /** + * @author yini-chen + * @description ampDebugger 工具函数 + */ +// import { emitter } from '@/utils/emitter'; +// import { ErrorField } from '@ali/api-component'; +import _ from 'lodash'; +import { ErrorField } from "../../../../SemixFormRender/context"; + +export const schemaTraversal = (schema, parentPath?: string) => { + if (!schema) return; + schema.path = parentPath ? parentPath + '.' + schema?.name : schema?.name; + // 删除空的enum + if (Array.isArray(schema?.enum) && schema?.enum?.length === 0) { + delete schema.enum; + } + if (schema.hasOwnProperty('exclusiveMaximum')) { + delete schema.exclusiveMaximum; + } + if (schema.hasOwnProperty('exclusiveMinimum')) { + delete schema.exclusiveMinimum; + } + if (schema?.format === 'int32' && !schema?.maximum) { + schema.maximum = 2147483647; + } + if ( + schema?.type === 'number' || + (schema?.type === 'integer' && schema?.format === 'int64') || + schema?.format === 'double' + ) { + schema.type = 'string'; + schema.pattern = schema?.pattern?.length ? schema.pattern : '^(-|+)?d+(.d+)?$'; + } + if (schema?.$ref) { + schema.ref = schema.$ref; + delete schema.$ref; + } + if (schema?.type && schema?.type === 'array' && schema?.items) { + schema.items.name = 'items'; + schemaTraversal(schema?.items, schema.path); + } + if (schema?.type && schema?.type === 'object' && schema?.properties) { + Object.keys(schema?.properties).map((key) => { + schema.properties[key].name = key; + schemaTraversal(schema?.properties[key], `${schema.path}.properties`); + }); + } + if (schema?.type && schema?.type === 'object' && schema?.additionalProperties) { + schemaTraversal(schema?.additionalProperties, `${schema.path}.additionalProperties`); + } + if (!schema?.description && schema?.title) { + schema['description'] = schema.title; + } + schemaTraversal(schema?.schema, schema.path); +}; + +export const getFormatParams = (meta, form) => { + const newMeta = [...meta]; + newMeta?.map((param) => { + // 请求参数有body的情况,如果body里的参数有必填,则body必填 + if (param.schema?.name === 'body') { + const body = form?.schema?.current?.properties?.body || null; + if (body?.required?.length) { + param.schema.required = true; + } + } + param.schema.name = param.name; + // 参数分组 + // if (Object.keys(categoryObj || {})?.length) { + // Object.keys(categoryObj || {}).map((key, index) => { + // if (categoryObj[key].includes(param.name)) { + // param.schema.group = key; + // param.schema.groupIndex = index + 1; + // } + // }); + // } + schemaTraversal(param.schema); + }); + return newMeta; +}; + +// export const addParamStruct = (schemaPath, schema) => { +// emitter.emit('addStruct', { schemaPath, schema }); +// }; + +export const addNewStruct = (parameters, schemaPath, struct) => { + // const _struct = {...struct} + const _parameters = [...parameters]; + const travelSchema = (schema) => { + if (!schema) return; + if (`properties.${schema?.path}` === schemaPath && schema.ref) { + Object.keys(struct)?.map((key) => { + if (key !== 'path') { + schema[key] = struct[key]; + } + }); + schema.path = schema?.path + '.ref'; + delete schema.ref; + return; + } + if (schema?.type && schema?.type === 'array' && schema?.items) { + travelSchema(schema?.items); + } + if (schema?.type && schema?.type === 'object' && schema?.properties) { + Object.keys(schema?.properties).map((key) => { + travelSchema(schema?.properties[key]); + }); + } + travelSchema(schema?.schema); + }; + + _parameters?.map((param) => { + travelSchema(param?.schema); + }); + return _parameters; +}; + +export const getFormatValues = (paramValues: any, apiParams, purpose?: string) => { + if (!apiParams?.length) { + return {}; + } + + const newAPIParamValues = _.cloneDeep(paramValues || {}); + + // 调试器校验前的valueformat不需要转换object(json) + if (purpose !== 'validate') { + Object.keys(newAPIParamValues || {})?.map((key) => { + if (key !== 'endpoint' && !apiParams?.find((item) => item.name === key)) { + delete newAPIParamValues?.[key]; + } + // 处理object类型,但需要往后端传json string类型的参数值(不能仅仅用 style 为 json 进行判断) + if ( + apiParams?.find( + (item) => + item.name === key && + item.schema?.type === 'object' && + !item.schema?.properties && + !item.schema?.additionalProperties, + ) + ) { + try { + newAPIParamValues[key] = JSON.stringify(newAPIParamValues[key]); + } catch (e) { + newAPIParamValues[key] = ''; + } + } + }); + } else { + // 兼容校验问题 + Object.keys(newAPIParamValues || {})?.map((key) => { + if (key !== 'endpoint' && !apiParams?.find((item) => item.name === key)) { + delete newAPIParamValues?.[key]; + } + // 处理object类型,但需要往后端传json string类型的参数值(不能仅仅用 style 为 json 进行判断) + if ( + apiParams?.find( + (item) => + item.name === key && + item.schema?.type === 'any' && + !item.schema?.properties && + !item.schema?.additionalProperties && + typeof newAPIParamValues[key] === 'string', + ) + ) { + try { + newAPIParamValues[key] = JSON.parse(newAPIParamValues[key]); + } catch (e) { + newAPIParamValues[key] = {}; + } + } + }); + } + + const travelObj = (values) => { + // 不再过滤空字符串 + Object.keys(values || {})?.map((key) => { + if (values[key] === undefined) { + delete values?.[key]; + } + if (typeof values[key] === 'object' && !Array.isArray(values[key])) { + if (isEmptyObj(values[key])) { + delete values?.[key]; + } + travelObj(values[key]); + } + if (Array.isArray(values[key])) { + if (values[key]?.length === 0) { + delete values?.[key]; + } else { + values[key].map((item, index) => { + if (item === undefined) { + values[key].splice(index, 1); + } + if (typeof item === 'object') { + if (isEmptyObj(item)) { + values[key].splice(index, 1); + } + travelObj(item); + } + }); + } + } + }); + }; + + const isEmptyObj = (obj) => { + let isEmpty = true; + + Object.keys(obj || {}).forEach((key) => { + if (obj[key] === '') { + isEmpty = false; + } + if (key === '') { + isEmpty = true; + } + if (obj[key] || key !== '') { + if (Array.isArray(obj[key]) && obj[key].length) { + isEmpty = false; + } + if (['string'].includes(typeof obj[key]) && !!obj[key]) { + isEmpty = false; + } + if (['number', 'boolean'].includes(typeof obj[key])) { + isEmpty = false; + } + if (_.isObject(obj[key]) && !_.isEmpty(obj[key])) { + isEmpty = false; + } + } + }); + return isEmpty; + }; + + travelObj(newAPIParamValues); + return newAPIParamValues; +}; + +export const handleExample = (schema, example) => { + if (['array', 'object', 'map'].includes(schema.type)) { + return undefined; + } else if (schema.type === 'number') { + return Number(example); + } else if (schema.type === 'boolean') { + if (schema.example === 'true') { + return true; + } else { + return false; + } + } else { + return schema.example; + } +}; + +export const stringToType = (type: string, value: string) => { + switch (type) { + case 'number': + return Number(value); + case 'boolean': + if (value === 'true') { + return true; + } + return false; + default: + return value; + } +}; + +export const getErrorWarningTip = (errors: ErrorField[]) => { + let errTip = ''; + errors?.map((error) => { + const errorMsg = `${error.dataPath}${error.message}`; + errTip = errTip?.length ? errTip + ',' + errorMsg : errorMsg; + }); + return errTip; +}; diff --git a/media/src/components/APIPage/TryAPI/TryAPI.module.css b/media/src/components/APIPage/TryAPI/TryAPI.module.css new file mode 100644 index 0000000..64ec9be --- /dev/null +++ b/media/src/components/APIPage/TryAPI/TryAPI.module.css @@ -0,0 +1,187 @@ +.comp-try-api { + position: relative; + padding: 16px; + height: 100%; + .ant-btn { + margin-left: 8px; + padding: 8px; + background-color: #f8f9fa; + border: 1px #f8f9fa solid; + } + .ant-btn:hover{ + background-color: #fff; + border: 1px #2f84ae solid; + color: #2f84ae; + } + + .ant-alert { + margin-bottom: 16px; + font-size: 12px; + background-color: #FFF4DD; + border: none !important; + .ant-alert-content { + .smart-debugger-wrapper { + display: inline-block; + } + } + } + .ant-alert-error { + background-color: #FFF5F5; + } + + .ant-spin-nested-loading { + position: absolute; + z-index: 1; + width: 100%; + height: 100%; + text-align: center; + background: rgba(247, 246, 246, 0.6); + } + + .api-result { + width: 100%; + min-height: 300px; + + .api-res-header { + + .title { + margin-bottom: 16px; + color: #303030; + font-size: 14px; + font-family: PingFangSC; + font-weight: 500; + color: #333333; + text-align: left; + } + .res-info{ + margin: 0 0 16px 0; + &>.item { + display: inline-block; + margin-right: 24px; + vertical-align: middle; + margin: 0 4px; + .debug-res{ + display: flex; + } + .label { + font-family: PingFangSC; + font-weight: 400; + font-size: 12px; + color: #808080; + margin-right: 4px; + .icon-success { + color: #00A700; + } + .icon-error { + color: #C80000; + } + .icon-forbidden { + color: #696969; + } + } + .value { + font-family: PingFangSC; + font-weight: 500; + font-size: 12px; + color: #333333; + } + .result-status { + padding: 0 8px; + border-radius: 2px; + } + .success { + color: #00A700; + } + .error-red { + color: #C80000; + } + } + } + + .feed-back { + display: flex; + align-items: center; + float: right; + margin-right: 10px; + color: #8e8e8e; + font-size: 12px; + + .workbench-feedback-generic { + display: inline-block; + display: inline-block; + margin-top: 0; + margin-right: 4px; + margin-left: 5px; + .value { + line-height: 23px; + } + } + } + } + + .content { + padding-top: 1px; + height: 425px; + .title { + margin-bottom: 8px; + font-family: PingFangSC; + font-weight: 500; + font-size: 14px; + color: #333333; + } + + .editor-container-box { + width: 100%; + max-height: 340px; + padding-top: 1px; + .editor-container { + border-color: #C0C6CC; + .header { + height: 40px; + line-height: 40px; + background-color: #F1F1F2; + border-radius: 4px 4px 0 0; + border-color: #C0C6CC; + .statics-lines { + font-size: 12px; + font-weight: 500; + } + .right-ops { + margin-right: 0; + .try-api-copy-button{ + border-radius: 2px; + width: 24px; + height: 24px; + line-height: 24px; + padding: 0; + .icon-copy-line { + vertical-align: top; + font-size: 12px; + margin-right: 0px; + } + } + } + } + .editor-box { + height: calc(100% - 32px); + .editor { + .line-numbers { + color: #333333; + font-weight: 500; + } + } + } + } + } + } + } + + .ant-empty { + height: 400px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + } + \ No newline at end of file diff --git a/media/src/components/APIPage/TryAPI/TryAPI.tsx b/media/src/components/APIPage/TryAPI/TryAPI.tsx index 47a7c29..f90ebfb 100644 --- a/media/src/components/APIPage/TryAPI/TryAPI.tsx +++ b/media/src/components/APIPage/TryAPI/TryAPI.tsx @@ -1,26 +1,23 @@ /** - * @author nianyi + * @author yini-chen * @description API 试用 */ import _ from "lodash"; -import { getIsUploadApi, parseXml } from "../../utils"; +import { getEditorMenuItems, getIsUploadApi, parseXml } from "../../utils"; import React from "react"; -import { Alert, Empty, Spin, message } from "antd"; +import { Alert, Button, Dropdown, Empty, Spin, message } from "antd"; import CopyToClipboard from "react-copy-to-clipboard"; -import { Button, Tab } from "@alicloud/console-components"; +import { Balloon, Tab } from "@alicloud/console-components"; import Editor from "@monaco-editor/react"; import I18N from "../../../utils/I18N"; import { APIResponse } from "../../../types/WorkbenchAPI"; import { EditorLanguages } from "../../../types/EditorLanguages"; import { OpenAPIRequestResult } from "../../../types/openAPI"; -import { WorkbenchIcon } from "../../../Icon/Icon"; import { APIPageContext } from "../context"; import { apiResponse } from "../../../mocks/openApiResponse"; -export class TryAPIProps { - -} +export class TryAPIProps {} const TAB_PANES = [ { @@ -38,8 +35,9 @@ const TAB_PANES = [ ]; export const TryAPI: React.FC = (props) => { - const { openAPIResponses, isApiResultLoading,version,apiMeta, product } = APIPageContext.useContainer(); - const doc = `${product}::${version}::${apiMeta.name}` + const { openAPIResponses, isApiResultLoading, version, apiMeta, product, mode } = APIPageContext.useContainer(); + const doc = `${product}::${version}::${apiMeta.name}`; + const [tab, setTab] = React.useState(TAB_PANES[0].value); const apiResult = openAPIResponses?.[doc]; const noShowMonacoEditor = ["byte"]; @@ -113,15 +111,6 @@ export const TryAPI: React.FC = (props) => { return res; }; - const copyBtn = (tab) => ( - message.success(I18N.main.explorer.copySuccess)} - > - - - ); const getResponseSchema = (statusCode, responseSchema) => { if (!statusCode || _.isEmpty(responseSchema)) { @@ -133,16 +122,37 @@ export const TryAPI: React.FC = (props) => { return responseSchema[statusCode]?.schema || {}; }; + const items = [ + ...getEditorMenuItems(getTabValue(tab), "json"), + { + key: "gotoweb", + label: ( + + 去门户网页版调试 + + ), + codicon: "link-external", + onClick: () => { + // window.open(apiMeta?.externalDocs?.url, "_blank"); + }, + }, + ]; + return (
+ 请利用 aliyun-cli 配置您的 AK/SK 信息:1. 安装 aliyun-cli: brew install aliyun-cli; 2. 命令行输入 aliyun + configure。 + 点击查看更多信息。 +
} type="warning" showIcon closable /> + {apiResult?.result || isApiResultLoading ? (
{isApiResultLoading ? ( @@ -156,18 +166,26 @@ export const TryAPI: React.FC = (props) => { {/* {apiResult?.result || props.isApiResultLoading ? ( */}
- - - - - {String(statusCode).startsWith("2") ? I18N.main.explorer.success : I18N.main.explorer.error} - +
+
+
+ {String(statusCode).startsWith("2") ? I18N.main.explorer.success : I18N.main.explorer.error} +
+
{apiResult && statusCode ? (
{/* {httpStatusMessageMap[statusCode] || statusCode} */} {I18N.main.explorer.statusCode} - + {statusCode}
@@ -175,7 +193,7 @@ export const TryAPI: React.FC = (props) => { {apiResult ? (
{I18N.main.explorer.time} - {/* {apiResult.cost}ms */} + {apiResult.cost}ms
) : null}
@@ -194,7 +212,6 @@ export const TryAPI: React.FC = (props) => { } - style={{ marginTop: "16px", marginBottom: "-8px" }} > ) : null}
@@ -216,7 +233,37 @@ export const TryAPI: React.FC = (props) => { )}
- + + { + if (navigator.clipboard) { + navigator.clipboard.writeText(getTabValue(tab)); + message.success("复制成功"); + } + }} + > +
+ + } + > + 复制 + + + + + + } + onChange={(t: any) => setTab(t)} + > {TAB_PANES.map((tab) => { return ( @@ -243,40 +290,9 @@ export const TryAPI: React.FC = (props) => { } value={getTabValue(tab.value)} // schema={getResponseSchema(statusCode, props.responseSchema) || {}} - // operators={ - // props?.apiResult?.format === 'xml' && tab.value === 'preview' ? ( - // <> - // {currentFormat === 'xml' ? ( - // - // ) : ( - // - // )} - // {copyBtn(tab)} - // - // ) : ( - // { - // message.success(I18N.main.explorer.copySucc); - // }} - // > - // - // - // ) - // } /> ) : (
{I18N.main.explorer.specialresponsetip}
- // )}
diff --git a/media/src/components/APIPage/TrySDK/LanguageSwitcher.module.scss b/media/src/components/APIPage/TrySDK/LanguageSwitcher.module.scss new file mode 100644 index 0000000..bd92e68 --- /dev/null +++ b/media/src/components/APIPage/TrySDK/LanguageSwitcher.module.scss @@ -0,0 +1,148 @@ +.language-switcher-comp { + .ant-tabs { + .ant-tabs-extra-content { + display: inline-block; + margin-right: 20px; + color: #666666; + font-weight: 500; + } + &>.ant-tabs-nav::before { + border: none; + } + } + .ant-tabs-nav { + height: 32px; + margin-bottom: 16px; + color: #303030; + line-height: 32px; + padding-left: 0; + border: none; + box-shadow: none; + + .ant-tabs-extra-content { + .label { + &::after { + content: ':'; + } + } + } + + .oa-iconfont.icon-dara { + margin-right: -15px; + margin-left: -15px; + font-size: 18px; + vertical-align: -0.1em; + } + .ant-tabs-nav-more { + border: 1px solid #CBCBCB; + .anticon { + vertical-align: 0.4em; + } + } + } + + .ant-tabs-nav-wrap { + margin-left:16px; + .ant-tabs-nav-list { + padding-left: 0px !important; + .ant-tabs-tab { + margin-right: -1px !important; + padding: 8px 16px !important; + font-size: 12px; + border: none; + border: 1px solid #CBCBCB; + border-radius: 0px; + background-color: #fff; + &:nth-last-child(2) { + margin-right: 0px !important; + } + } + .ant-tabs-tab-active { + border: 1px solid #FF6A00; + position: relative; + z-index: 999; + } + } + + .oa-iconfont { + margin-right: 2px; + font-size: 14px; + vertical-align: 0; + + &.icon-java { + font-size: 16px; + vertical-align: -0.25em; + } + + &.icon-typescript { + font-size: 16px; + vertical-align: -0.25em; + } + + &.icon-python { + font-size: 16px; + vertical-align: -0.2em; + } + + &.icon-php { + font-size: 26px; + vertical-align: -0.3em; + } + + &.icon-go { + font-size: 26px; + vertical-align: -0.3em; + } + + &.icon-csharp { + vertical-align: -0.15em; + } + + &.icon-node-js { + vertical-align: -0.15em; + } + + &.icon-ruby { + vertical-align: -0.2em; + } + &.icon-cpp { + vertical-align: -0.2em; + } + &.icon-swift { + font-size: 20px; + vertical-align: -0.2em; + } + } + } + + .right-ops { + .ant-btn { + margin-right: 12px; + } + + .infos { + vertical-align: middle; + .item { + margin-left: 12px; + color: #fb6220; + cursor: pointer; + } + + .sep-line { + display: inline-block; + width: 1px; + height: 22px; + margin: 0 10px; + line-height: 22px; + vertical-align: middle; + background-color: #d8d8d8; + } + } + } + + .empty-card { + margin-top: 16px; + } + } + + \ No newline at end of file diff --git a/media/src/components/APIPage/TrySDK/LanguageSwitcher.tsx b/media/src/components/APIPage/TrySDK/LanguageSwitcher.tsx new file mode 100644 index 0000000..f2451ae --- /dev/null +++ b/media/src/components/APIPage/TrySDK/LanguageSwitcher.tsx @@ -0,0 +1,74 @@ +/** + * @author yini-chen + * @description 语言切换 + */ +import { Card, Empty, Select, Tabs } from "antd"; +import * as React from "react"; +// import { WorkbenchIcon } from './Icon/Icon'; +// import { EditorLanguages } from './MonacoEditor/define'; +// import { I18N } from '../utils/I18N'; +import { EditorLanguages } from "../../define"; +import I18N from "../../../utils/I18N"; +import { WorkbenchIcon } from "../../../Icon/Icon"; + +export const OLD_SDK_LANGUAAGES = [ + { value: EditorLanguages.Java, text: EditorLanguages.Java, icon: "java" }, + { value: EditorLanguages.Javascript, text: "Node.js", icon: "node-js" }, + { value: EditorLanguages.Go, text: EditorLanguages.Go, icon: "go" }, + { value: EditorLanguages.PHP, text: EditorLanguages.PHP, icon: "php" }, + { value: EditorLanguages.Python, text: EditorLanguages.Python, icon: "python" }, + { value: EditorLanguages.CSharp, text: "C#", icon: "csharp" }, + { value: EditorLanguages.Ruby, text: EditorLanguages.Ruby, icon: "ruby" }, + { value: EditorLanguages.CPP, text: "C++", icon: "cpp" }, +]; + +export const DARA_SDK_LANGUAGES = [ + { value: EditorLanguages.JavaAsync, text: EditorLanguages.JavaAsync, icon: "java" }, + { value: EditorLanguages.Java, text: EditorLanguages.Java, icon: "java" }, + { value: EditorLanguages.TypeScript, text: "TypeScript", icon: "typescript" }, + { value: EditorLanguages.Go, text: EditorLanguages.Go, icon: "go" }, + { value: EditorLanguages.PHP, text: EditorLanguages.PHP, icon: "php" }, + { value: EditorLanguages.Python, text: EditorLanguages.Python, icon: "python" }, + { value: EditorLanguages.Python2, text: EditorLanguages.Python2, icon: "python" }, + + { value: EditorLanguages.CSharp, text: "C#", icon: "csharp" }, + { value: EditorLanguages.CPP, text: "C++", icon: "cpp" }, + { value: EditorLanguages.Swift, text: "Swift", icon: "swift" }, +] as Array<{ value: string; text: string; icon: string; disabled: boolean }>; + +export class LanguageSwitcherProps { + languages? = DARA_SDK_LANGUAGES; + + language?: string; + + tabContent: React.ReactNode; + + onLanguageChange(language: EditorLanguages) {} + + extra = null; + languageStatus? = {}; +} + +export const LanguageSwitcher: React.FC = (props) => { + const options = props.languages.map((language) => { + return { + value: language.value, + label: language.text, + key: language.value, + disabled:language.disabled + }; + }); + + return ( +
+ +
+ ); +}; + +LanguageSwitcher.defaultProps = new LanguageSwitcherProps(); diff --git a/media/src/components/APIPage/TrySDK/TrySDK.module.scss b/media/src/components/APIPage/TrySDK/TrySDK.module.scss new file mode 100644 index 0000000..e69de29 diff --git a/media/src/components/APIPage/TrySDK/TrySDK.tsx b/media/src/components/APIPage/TrySDK/TrySDK.tsx new file mode 100644 index 0000000..e08c401 --- /dev/null +++ b/media/src/components/APIPage/TrySDK/TrySDK.tsx @@ -0,0 +1,145 @@ +/** + * @author yini-chen + * @description + */ +import React from "react"; +import { DARA_SDK_LANGUAGES, LanguageSwitcher } from "./LanguageSwitcher"; +import { Editor } from "@monaco-editor/react"; +import { codes } from "../../../mocks/makeCode"; +import { MenuProps, Tag } from "antd"; +import { PontUIService } from "../../../service/UIService"; +import { APIPageContext } from "../context"; +import { Button } from "@alicloud/console-components"; +import { getVSCode } from "../../../utils/utils"; +import MonacoEditor from "../../common/MonacoEditor"; + +export class TrySDKProps {} + +export const TrySDK: React.FC = (props) => { + // const daraSdkLannguages = SDKPublishInfo.getDaraLanguages(props.sdkInfos || [], product, version); + const { apiMeta, schemaForm, product, version, onDebug, changeMode, endpoints, regionId, mode } = + APIPageContext.useContainer(); + const [languageTab, setLanguageTab] = React.useState("Java"); + const [sdkDemos, setSdkDemos] = React.useState(codes.demoSdk as any); + + React.useEffect(() => { + PontUIService.getLocalLanguage().then((res) => { + if (res?.length) { + setLanguageTab(res); + } else { + setLanguageTab("Java"); + } + }); + }); + + React.useEffect(() => { + PontUIService.makeCodeRequest({ + paramsValue: schemaForm.formData, + apiMeta: apiMeta, + product, + version, + endpoint: endpoints?.find((item) => item.regionId === regionId)?.public, + regionId: regionId, + }).then((res) => { + setSdkDemos(res?.data?.demoSdk || codes.demoSdk); + }); + }, [schemaForm.formData, regionId, apiMeta?.name, product, version, endpoints]); + + const getEditorLanguage = (lang) => { + switch (lang) { + case "java-async": + return "java"; + case "Java": + return "java"; + case "TypeScript": + return "typescript"; + case "Go": + return "go"; + case "PHP": + return "php"; + case "Python": + return "python"; + case "Python2": + return "python"; + case "CSharp": + return "csharp"; + case "cpp": + return "cpp"; + case "swift": + return "swift"; + default: + return "javascript"; + } + }; + + React.useEffect(() => { + if (mode === "sdk") { + getVSCode()?.setState({ + ...getVSCode()?.getState(), + code: sdkDemos[languageTab?.toLocaleLowerCase()], + language: languageTab, + }); + } + }, [mode, languageTab, sdkDemos[languageTab?.toLocaleLowerCase()]]); + + + const tabContent = React.useMemo(() => { + return sdkDemos ? ( +
+ +
+ ) : null; + }, [languageTab, sdkDemos]); + + const getCode = React.useCallback(()=>{ + if(!sdkDemos[languageTab?.toLocaleLowerCase()]){ + return "// API 暂未支持该语言的 SDK" + } + return sdkDemos[languageTab?.toLocaleLowerCase()] + },[sdkDemos, languageTab]) + + return React.useMemo(() => { + return ( +
+ + sdk | v2.0 +
+ } + menuItems={[{ + key: "gotoweb", + label: "去门户网页版调试", + codicon:"link-external", + externalLink: apiMeta?.externalDocs?.url, + onClick: () => { + // window.open(apiMeta?.externalDocs?.url, "_blank"); + }, + }]} + value={getCode()} + languages={DARA_SDK_LANGUAGES?.map((lang) => { + if (Object.keys(sdkDemos || {})?.includes(lang?.value?.toLocaleLowerCase())) { + return lang; + } else { + return { ...lang, disabled: true }; + } + })} + > +
+ ); + }, [languageTab, sdkDemos, tabContent]); +}; +TrySDK.defaultProps = new TrySDKProps(); +export default TrySDK; diff --git a/media/src/components/APIPage/context.ts b/media/src/components/APIPage/context.ts index 77ce6cc..536a988 100644 --- a/media/src/components/APIPage/context.ts +++ b/media/src/components/APIPage/context.ts @@ -1,11 +1,13 @@ /** - * @author nianyi + * @author yini-chen */ import { createContainer } from 'unstated-next'; import { SemixFormProps } from '../SemixFormRender'; import React from 'react'; import { PontUIService } from '../../service/UIService'; -import { ExtensionResponse, OpenAPIRequestResult } from '../../types/openAPI'; +import { OpenAPIResponse, OpenAPIRequestResult } from '../../types/openAPI'; +import { endpointsMocks } from '../../mocks/endpoints'; +import { getVSCode } from '../../utils/utils'; export class APIPageState { /** @@ -30,15 +32,40 @@ export class APIPageState { * 发起调用loading */ isApiResultLoading? = false + /** + * 模式选择 + */ + mode: 'debug' | 'doc' |'sdk' = 'debug'; + changeMode: (mode: 'debug' | 'doc' | 'sdk') => void; + /** + * 服务地址 + */ + endpoints?: any[]; + /** + * regionId + */ + regionId? = 'cn-hangzhou'; + setRegionId?: (regionId: string) => void; } export const useAPIPageContext = (initialState = {} as APIPageState): APIPageState => { const [openAPIResponses, setOpenAPIResponse] = React.useState(null); const [isApiResultLoading, setIsApiResultLoading] = React.useState(false); + const [endpoints, setEndpoints] = React.useState([]); + const [regionId, setRegionId] = React.useState("cn-hangzhou"); + + React.useEffect(() => { + if (endpoints.length === 0) { + // get endpoints list + PontUIService.requestEndpoints(initialState.product).then((res) => { + setEndpoints(res?.length ? res : endpointsMocks); + }); + } + }, [initialState.product]); + const onDebug = (value) =>{ setIsApiResultLoading(true); PontUIService.openAPIRequest(value).then(res=>{ - console.log("webview 收到的信息", res) setIsApiResultLoading(false); const responses = {}; // 根据文档名存储响应,切换API文档时展示对应的响应 @@ -46,7 +73,7 @@ export const useAPIPageContext = (initialState = {} as APIPageState): APIPageSta setOpenAPIResponse(responses); }); } - return { ...initialState, openAPIResponses, onDebug, isApiResultLoading }; + return { ...initialState, openAPIResponses, onDebug, isApiResultLoading, endpoints, regionId, setRegionId }; }; export const APIPageContext = createContainer(useAPIPageContext); \ No newline at end of file diff --git a/media/src/components/SemixFormRender/SemixForm.tsx b/media/src/components/SemixFormRender/SemixForm.tsx index 8a1e1ae..08ca40f 100644 --- a/media/src/components/SemixFormRender/SemixForm.tsx +++ b/media/src/components/SemixFormRender/SemixForm.tsx @@ -9,7 +9,7 @@ import { getSchemaByRef, semixifySchema, usePrevious } from "./utils"; import { SemixUISchema } from "./type"; import { FormInstance, FormStoreContext, FormStoreIntialState, useForm } from "./context"; import { Field } from "./common/Field"; -import { useDeepCompareMemo } from "use-deep-compare"; +// import { useDeepCompareMemo } from "use-deep-compare"; import { FormItem } from "./common/FormItem"; import { getFieldClassName } from "./utils"; import classNames from "classnames"; diff --git a/media/src/components/SemixFormRender/context.tsx b/media/src/components/SemixFormRender/context.tsx index 2d18b13..6ebb1fb 100644 --- a/media/src/components/SemixFormRender/context.tsx +++ b/media/src/components/SemixFormRender/context.tsx @@ -88,11 +88,11 @@ export function useForm(initProps = new FormProps()) { if (hasDynamicSchemaResult) { return schema; } - if (schema.visible && typeof schema.visible === "string") { + if (schema?.visible && typeof schema?.visible === "string") { hasDynamicSchemaResult = true; return schema; } - if (schema.dynamic) { + if (schema?.dynamic) { hasDynamicSchemaResult = true; return schema; } diff --git a/media/src/components/SemixFormRender/langs/zh_CN/apiDebugger.ts b/media/src/components/SemixFormRender/langs/zh_CN/apiDebugger.ts index 177f9fe..b1020b7 100644 --- a/media/src/components/SemixFormRender/langs/zh_CN/apiDebugger.ts +++ b/media/src/components/SemixFormRender/langs/zh_CN/apiDebugger.ts @@ -1,9 +1,9 @@ export default { - "index": { - "empty": "清空", - "submissionFailure": "提交失败。", - "submittedSuccessfully": "提交成功", - "submit": "提交", - "lookOnlyAtRequired": "只看必填", + index: { + empty: '清空', + submissionFailure: '提交失败。', + submittedSuccessfully: '提交成功', + submit: '提交', + lookOnlyAtRequired: '只看必填', }, }; diff --git a/media/src/components/SemixFormRender/utils.tsx b/media/src/components/SemixFormRender/utils.tsx index 8458004..63bc9d9 100644 --- a/media/src/components/SemixFormRender/utils.tsx +++ b/media/src/components/SemixFormRender/utils.tsx @@ -219,7 +219,7 @@ export const semixifySchema = (resultSchema: SemixJsonSchema, getCustomWidget?) if (schema?.type === "object" && schema?.properties) { let newRequired = Object.keys(schema.properties).filter((key) => { - return schema.properties[key].required || schema.properties[key].isRequired; + return schema.properties[key]?.required || schema.properties[key]?.isRequired; }); let newProperties = schema?.properties; if (schema?.required?.length) { diff --git a/media/src/components/SemixFormRender/widgets/xconsole/JsonEdit.tsx b/media/src/components/SemixFormRender/widgets/xconsole/JsonEdit.tsx index 6a55121..aa72ec1 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/JsonEdit.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/JsonEdit.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description 表单 Json 编辑器 */ diff --git a/media/src/components/SemixFormRender/widgets/xconsole/Object.tsx b/media/src/components/SemixFormRender/widgets/xconsole/Object.tsx index c61d75c..11a477f 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/Object.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/Object.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description amp定制object,object回填value可能为string */ import * as React from "react"; diff --git a/media/src/components/SemixFormRender/widgets/xconsole/checkbox.tsx b/media/src/components/SemixFormRender/widgets/xconsole/checkbox.tsx index 3e91376..cd26aad 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/checkbox.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/checkbox.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description 枚举选择 */ diff --git a/media/src/components/SemixFormRender/widgets/xconsole/enum.tsx b/media/src/components/SemixFormRender/widgets/xconsole/enum.tsx index ddc7644..792ad30 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/enum.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/enum.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description 枚举选择 */ diff --git a/media/src/components/SemixFormRender/widgets/xconsole/map.tsx b/media/src/components/SemixFormRender/widgets/xconsole/map.tsx index 5ece83a..fdf387e 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/map.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/map.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description semix-map */ import * as React from "react"; diff --git a/media/src/components/SemixFormRender/widgets/xconsole/number.tsx b/media/src/components/SemixFormRender/widgets/xconsole/number.tsx index 7d74956..124b6fa 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/number.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/number.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description 输入数值 */ import { NumberPicker } from "@alicloud/console-components"; diff --git a/media/src/components/SemixFormRender/widgets/xconsole/radio.tsx b/media/src/components/SemixFormRender/widgets/xconsole/radio.tsx index 9d45620..a8edfef 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/radio.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/radio.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description 枚举选择 */ diff --git a/media/src/components/SemixFormRender/widgets/xconsole/string.tsx b/media/src/components/SemixFormRender/widgets/xconsole/string.tsx index 4ff6642..23e493f 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/string.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/string.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description string类型 */ diff --git a/media/src/components/SemixFormRender/widgets/xconsole/swtich.tsx b/media/src/components/SemixFormRender/widgets/xconsole/swtich.tsx index dd491d5..fd86bca 100644 --- a/media/src/components/SemixFormRender/widgets/xconsole/swtich.tsx +++ b/media/src/components/SemixFormRender/widgets/xconsole/swtich.tsx @@ -1,5 +1,5 @@ /** - * @author nianyi + * @author yini-chen * @description Switch */ import * as React from "react"; diff --git a/media/src/components/common/MonacoEditor.scss b/media/src/components/common/MonacoEditor.scss new file mode 100644 index 0000000..0dc3660 --- /dev/null +++ b/media/src/components/common/MonacoEditor.scss @@ -0,0 +1,42 @@ +.editor-content { + .operations { + display: flex; + margin: 16px 0 16px 0px; + padding: 8px 16px; + justify-content: space-between; + .right-area { + display: flex; + .ant-btn { + margin-left: 8px; + padding: 0px; + background-color: #f8f9fa; + border: 1px #f8f9fa solid; + } + .ant-btn:hover{ + background-color: #fff; + border: 1px #2f84ae solid; + color: #2f84ae; + } + + } + .left-area { + display: flex; + margin: auto 0; + width: 200px; + .head-info { + margin: auto 8px; + } + } + .codicon { + padding: 8px; + cursor: pointer; + color:#6e6e6e; + } + .codicon:hover{ + color: #2f84ae; + } + } + .tab-content { + position: relative; + } +} diff --git a/media/src/components/common/MonacoEditor.tsx b/media/src/components/common/MonacoEditor.tsx new file mode 100644 index 0000000..0409e7d --- /dev/null +++ b/media/src/components/common/MonacoEditor.tsx @@ -0,0 +1,149 @@ +/** + * @author yini-chen + * @description 编辑器 + */ +import { Editor } from "@monaco-editor/react"; +import React, { ReactNode } from "react"; +import { DARA_SDK_LANGUAGES, LanguageSwitcher } from "../APIPage/TrySDK/LanguageSwitcher"; +import { Button, Dropdown, MenuProps, Tooltip, message } from "antd"; +import { PontUIService } from "../../service/UIService"; +import { Balloon } from "@alicloud/console-components"; +import { getEditorLanguage, getEditorMenuItems } from "../utils"; + +export class MonacoEditorProps { + languageTab?: string; + setLanguageTab?: (lang) => void; + languageSelector? = true; + copyable? = true; + header?: React.ReactNode; + value? = ""; + readOnly? = true; + height? = 800; + languages? = DARA_SDK_LANGUAGES; + menuItems?: Array<{ key: string; label: ReactNode | string; codicon?: string; onClick: () => void, externalLink?:string }> = []; +} + +export const MonacoEditor: React.FC = (props) => { + const { + languageTab, + setLanguageTab, + languageSelector, + languages, + copyable, + header, + value, + readOnly, + height, + menuItems, + } = props; + + const items: Array<{ key: string; label: ReactNode | string; codicon?: string; onClick: () => void,externalLink?:string }> = [ + ...getEditorMenuItems(value, getEditorLanguage(languageTab)), + ...menuItems, + ]; + + const tabContent = React.useMemo(() => { + return value?.length ? ( +
+ +
+ ) : null; + }, [languageTab, value]); + + return ( +
+
+
+ {languageSelector ? ( + { + setLanguageTab(lang); + PontUIService.updateLocalLanguage(lang); + }} + tabContent={null} + > + ) : null} + {header || null} +
+
+ {copyable ? ( + { + if (navigator.clipboard) { + navigator.clipboard.writeText(value); + message.success("复制成功"); + } + }} + > +
+ + } + > + 复制 + + ) : null} + {items?.length ? ( +
+ {/* + + */} + {items?.map((item) => { + return ( + +
+ + } + > + {item.label} + + ); + })} + {/* {(window as any).vscode ? ( + + e.preventDefault()}> + fff +
+ + + ) : null} */} +
+ ) : null} +
+
+ {tabContent} +
+ ); +}; +MonacoEditor.defaultProps = new MonacoEditorProps(); +export default MonacoEditor; diff --git a/media/src/components/define.ts b/media/src/components/define.ts new file mode 100644 index 0000000..502cec0 --- /dev/null +++ b/media/src/components/define.ts @@ -0,0 +1,58 @@ +/** + * @file SQL编辑器定义文件 + * @author 奇阳 + */ + +export enum EditorLanguages { + /** Darabonba */ + Darabonba = 'Darabonba', + + TypeScript = 'TypeScript', + + Javascript = 'javascript', + + PHP = 'PHP', + + Ruby = 'Ruby', + + CSharp = 'CSharp', + + Markdown = 'markdown', + + /** Go 语言 */ + Go = 'Go', + + /** Java 语言 */ + Java = 'Java', + + /** Python 语言 */ + Python = 'Python', + + Python2 = 'Python2', + + JSON = 'json', + + XML = 'xml', + + Shell = 'shell', + + CPP = 'cpp', + + JavaAsync = 'java-async', + + Swift = 'swift', + } + + export interface SDKLanguage { + typescript: string; + java: string; + php: string; + python: string; + python2: string; + go: string; + csharp: string; + swift: string; + "java-async": string; + dependencies: string; +} + \ No newline at end of file diff --git a/media/src/components/main.tsx b/media/src/components/main.tsx index 7ec2613..6d437a7 100644 --- a/media/src/components/main.tsx +++ b/media/src/components/main.tsx @@ -5,8 +5,10 @@ import { getVSCode } from "../utils/utils"; import { parseAPIMetaDescription } from "../utils/parseAPIMetaDescription"; import { ApiErrorCode } from "./APIPage/APIDocument/ApiErrorCode"; import { PontUIService } from "../service/UIService"; -import "../pages/document/index.module.scss"; -import { routerMeta } from "../mocks/routerMeta"; +import "../pages/document/index.scss"; +// import { definitions } from "../mocks/definitions"; +// import { routerMeta } from "../mocks/routerMeta"; +// import { definitions } from "../mocks/definitions"; if (typeof window !== "undefined") { (window as any).routerMeta = {}; @@ -23,7 +25,7 @@ const getRouterMeta = (): any => { value = JSON.parse(decodeURI(routerMetaStr)); } catch (e) {} - getVSCode().setState(value); + getVSCode()?.setState(value); return value; }; diff --git a/media/src/components/utils.ts b/media/src/components/utils.ts index b3c1570..13ac8f2 100644 --- a/media/src/components/utils.ts +++ b/media/src/components/utils.ts @@ -1,9 +1,12 @@ import _ from "lodash"; import { APIResponse } from "../types/WorkbenchAPI"; import { Parser } from 'xml2js'; +import { EditorLanguages } from "./define"; +import { PontUIService } from "../service/UIService"; +import { getVSCode } from "../utils/utils"; export const getRefSchema = (schemas: any) => ($ref: string) => { - const schemaName = $ref.split("/").pop(); + const schemaName = $ref?.split("/").pop(); const schema = schemaName ? schemas?.[schemaName] : {}; if (schema) { return schema; @@ -27,3 +30,152 @@ export const parseXml = (body: string): any => { } return result.output; }; + +export const getLanguageEditorByLang = ( + lang: + | 'JAVA' + | 'NODEJS' + | 'GO' + | 'PHP' + | 'PYTHON' + | 'PYTHON2' + | 'CSHARP' + | 'RUBY' + | 'TYPESCRIPT' + | 'JAVAASYNC' + | 'SWIFT', +) => { + switch (lang) { + case 'CSHARP': { + return EditorLanguages.CSharp; + } + case 'GO': { + return EditorLanguages.Go; + } + case 'JAVA': { + return EditorLanguages.Java; + } + case 'JAVAASYNC': { + return EditorLanguages.JavaAsync; + } + case 'NODEJS': { + return EditorLanguages.Javascript; + } + case 'PHP': { + return EditorLanguages.PHP; + } + case 'PYTHON': { + return EditorLanguages.Python; + } + case 'PYTHON2': { + return EditorLanguages.Python2; + } + case 'RUBY': { + return EditorLanguages.Ruby; + } + case 'TYPESCRIPT': { + return EditorLanguages.TypeScript; + } + case 'SWIFT': { + return EditorLanguages.Swift; + } + default: { + return EditorLanguages.Javascript; + } + } +}; + +export const getLangByLanguageEditor = (language: EditorLanguages) => { + switch (language) { + case EditorLanguages.TypeScript: { + return 'TYPESCRIPT'; + } + case EditorLanguages.CSharp: { + return 'CSHARP'; + } + case EditorLanguages.Go: { + return 'GO'; + } + case EditorLanguages.Java: { + return 'JAVA'; + } + case EditorLanguages.JavaAsync: { + return 'JAVAASYNC'; + } + case EditorLanguages.Javascript: { + return 'NODEJS'; + } + case EditorLanguages.PHP: { + return 'PHP'; + } + case EditorLanguages.Python: { + return 'PYTHON'; + } + case EditorLanguages.Python2: { + return 'PYTHON2'; + } + case EditorLanguages.Ruby: { + return 'RUBY'; + } + case EditorLanguages.CPP: { + return 'CPP'; + } + case EditorLanguages.Swift: { + return 'SWIFT'; + } + default: { + return language; + } + } +}; + +export const getEditorMenuItems = (code, language):Array<{ key: string; label: string; codicon?: string; onClick: () => void }> => { + return [ + { + key: "openInCode", + label: "在 IDE 中打开", + codicon: "file-code", + onClick: () => { + PontUIService.openInCode({ + code: code, + language: language, + }); + }, + }, + { + key: "saveToFile", + label: "另存为...", + codicon: "save-as", + onClick: () => { + PontUIService.saveToFile(code || ""); + }, + }, + ]; +} + +export const getEditorLanguage = (lang) => { + switch (lang) { + case "java-async": + return "java"; + case "Java": + return "java"; + case "TypeScript": + return "typescript"; + case "Go": + return "go"; + case "PHP": + return "php"; + case "Python": + return "python"; + case "Python2": + return "python"; + case "CSharp": + return "csharp"; + case "cpp": + return "cpp"; + case "swift": + return "swift"; + default: + return "javascript"; + } +}; diff --git a/media/src/document.css b/media/src/document.css index fc68afb..76a2141 100644 --- a/media/src/document.css +++ b/media/src/document.css @@ -49350,9 +49350,6 @@ code { .pontx-ui-api .semix-table-header-th.param-name { min-width: 100px; } -.pontx-ui-api .api-page-content { - padding: 12px 20px 12px; -} .pontx-ui-api .desc-mod { background-color: #fff; border: 1px solid #89a6b5; diff --git a/media/src/langs/zh_CN/main.ts b/media/src/langs/zh_CN/main.ts index ef7ed9f..e1b514a 100644 --- a/media/src/langs/zh_CN/main.ts +++ b/media/src/langs/zh_CN/main.ts @@ -120,7 +120,7 @@ export default { contributionDemo: '贡献示例', seeResults: '查看结果', AKTip: - ' 平台通过已登录用户信息获取当前账号临时Access Keys、发起调用可能对当前账号发起线上资源操作,请小心操作', + '将通过您的配置信息获取 Access Keys、发起调用可能对当前账号发起线上资源操作,请小心操作', APICallResult: 'API 调用结果', overview: '概览', success: '调用成功', diff --git a/media/src/main.css b/media/src/main.css index 4a502b6..1efa71a 100644 --- a/media/src/main.css +++ b/media/src/main.css @@ -6,7 +6,16 @@ html body { border-left: 1px solid #d7d7d7; } .vscode-page { - padding: 20px; + padding: 20px 20px 0 20px; width: 100%; - max-width: 100%; + .api-page-content { + position: relative; + margin-top: 16px; + display: flex; + width: 100%; + .content{ + width: 100%; + padding:0 0 16px 20px + } + } } diff --git a/media/src/mocks/definitions.ts b/media/src/mocks/definitions.ts new file mode 100644 index 0000000..0ac3998 --- /dev/null +++ b/media/src/mocks/definitions.ts @@ -0,0 +1,3852 @@ +export const definitions = { + "AccessControlList": { + "title": "A list of grants that control access to the staged results", + "description": "存储ACL信息的容器。", + "type": "object", + "properties": { + "Grant": { + "description": "Bucket的读写权限ACL。", + "enumValueTitles": { + "private": "private", + "public-read": "public-read", + "public-read-write": "public-read-write" + }, + "example": "public-read", + "$ref": "#/components/schemas/Grant" + } + } + }, + "AccessControlPolicy": { + "title": "Contains the elements that set the ACL permissions for an object", + "description": "保存Get Object ACL结果的容器。", + "type": "object", + "properties": { + "Owner": { + "description": "保存Bucket拥有者信息的容器。\n\n", + "$ref": "#/components/schemas/Owner" + }, + "AccessControlList": { + "description": "存储ACL信息的容器。", + "$ref": "#/components/schemas/AccessControlList" + } + } + }, + "AccessMonitorConfiguration": { + "title": "A short description of struct", + "description": "Bucket的访问跟踪状态配置信息。", + "type": "object", + "properties": { + "Status": { + "description": "Bucket的访问跟踪状态。", + "$ref": "#/components/schemas/AccessMonitorStatus" + } + } + }, + "AccessMonitorStatus": { + "title": "A short description of struct", + "description": "Bucket的访问跟踪状态。取值范围如下:\n\n- Enabled:已开启\n\n- Disabled:未开启", + "type": "string", + "example": "Enabled", + "enum": [ + "Enabled", + "Disabled" + ] + }, + "AccessPoint": { + "title": "保存AccessPoint信息的容器", + "description": "保存单个接入点信息的容器。", + "type": "object", + "properties": { + "Bucket": { + "title": "Bucket名称", + "description": "配置接入点的Bucket名称。", + "type": "string", + "example": "oss-example" + }, + "AccessPointName": { + "title": "接入点名称", + "description": "接入点名称。", + "$ref": "#/components/schemas/AccessPointName" + }, + "Alias": { + "title": "接入点别名", + "description": "接入点别名。", + "$ref": "#/components/schemas/AccessPointAlias" + }, + "NetworkOrigin": { + "description": "接入点网络来源。", + "$ref": "#/components/schemas/AccessPointNetworkOrigin" + }, + "VpcConfiguration": { + "description": "保存VPC网络来源信息的容器。", + "$ref": "#/components/schemas/AccessPointVpcConfiguration" + }, + "Status": { + "description": "接入点所处状态。", + "$ref": "#/components/schemas/AccessPointStatus" + } + } + }, + "AccessPointAlias": { + "title": "接入点别名", + "description": "接入点别名。", + "type": "string", + "example": "ap-01-45ee7945007a2f0bcb595f63e2215c****-ossalias" + }, + "AccessPointArn": { + "title": "接入点ARN。", + "description": "接入点ARN。", + "type": "string", + "example": "arn:acs:oss:ap-southeast-2:111933544165****:accesspoint/ap-01" + }, + "AccessPointName": { + "title": "接入点名称", + "description": "接入点名称", + "type": "string", + "example": "ap-01" + }, + "AccessPointNetworkOrigin": { + "title": "接入点网络来源。返回值如下: vpc:限制仅支持通过指定的VPC ID访问接入点。 internet:同时持通过外网和内网Endpoint互联网访问接入点。", + "description": "接入点网络来源。返回值如下: vpc:限制仅支持通过指定的VPC ID访问接入点。 internet:同时持通过外网和内网Endpoint互联网访问接入点。", + "type": "string", + "example": "vpc" + }, + "AccessPointStatus": { + "title": "接入点所处状态", + "description": "接入点所处状态。\n\n- enable:接入点已创建完成。\n\n- disable:接入点已禁用。\n\n- creating:接入点正在创建中。\n\n- deleting:接入点已删除。", + "type": "string", + "example": "enable" + }, + "AccessPointVpcConfiguration": { + "title": "保存VPC网络来源信息的容器。", + "description": "保存VPC网络来源信息的容器。", + "type": "object", + "properties": { + "VpcId": { + "title": "仅当NetworkOrigin取值为vpc时,需要指定VPC ID。", + "description": "仅当NetworkOrigin取值为vpc时,需要指定VPC ID。", + "type": "string", + "example": "vpc-t4nlw426y44rd3iq4****" + } + } + }, + "ApplyServerSideEncryptionByDefault": { + "title": "A short description of struct", + "description": "服务器端默认加密方式的容器。\n", + "type": "object", + "properties": { + "SSEAlgorithm": { + "title": "description", + "description": "设置服务器端默认加密方式。\n取值:KMS、AES256、SM4\n使用KMS密钥功能时会产生少量的KMS密钥API调用费用,费用详情请参见**[KMS计费标准](~~52608~~)**。\n进行跨区域复制时,若目标Bucket启用了默认服务器端加密方式,且复制规则配置了ReplicaCMKID,有以下两种情况:\n - 若源Bucket中的对象未加密,则使用目标Bucket的默认加密方式对跨区域复制过来的明文对象进行加密。\n - 若源Bucket中的对象使用了SSE-KMS或SSE-OSS的加密方式,则目标Bucket针对这些对象仍然使用原加密方式进行加密。\n\n更多信息,请参见**[跨区域复制结合服务器端加密](~~177216~~)**。", + "type": "string", + "example": "AES256" + }, + "KMSMasterKeyID": { + "title": "description", + "description": "当SSEAlgorithm值为KMS,且使用指定的密钥加密时,需输入KMSMasterKeyID。其他情况下,必须为空。", + "type": "string", + "enumValueTitles": {}, + "example": "9468da86-3509-4f8d-a61e-6eab1eac****" + }, + "KMSDataEncryption": { + "title": "description", + "description": "指定Object的加密算法。若未指定此选项,表明Object使用AES256加密算法。此选项仅当SSEAlgorithm取值为KMS有效。\n取值:SM4", + "type": "string", + "enumValueTitles": {}, + "example": "SM4" + } + } + }, + "Bucket": { + "title": "Bucket信息", + "description": "保存Bucket信息的容器。", + "type": "object", + "properties": { + "CreationDate": { + "title": "Bucket的创建时间,格式为UTC时间", + "description": "Bucket创建时间。格式为`yyyy-mm-ddThh:mm:ss.timezone`。", + "type": "string", + "format": "iso8601", + "example": "2014-05-15T11:18:32.000Z" + }, + "ExtranetEndpoint": { + "title": "Bucket的外网域名", + "description": "Bucket访问的外网域名。", + "type": "string", + "example": "oss-cn-hangzhou.aliyuncs.com" + }, + "IntranetEndpoint": { + "title": "Bucket的内网域名", + "description": "同地域ECS访问Bucket的内网域名。", + "type": "string", + "example": "oss-cn-hangzhou-internal.aliyuncs.com" + }, + "Location": { + "title": "Bucket所在的数据中心", + "description": "Bucket所在的数据中心。", + "type": "string", + "example": "oss-cn-hangzhou" + }, + "Name": { + "title": "Bucket的名称", + "description": "Bucket名称。", + "type": "string", + "example": "mybucket01" + }, + "StorageClass": { + "title": "Bucket的存储类型", + "description": "Bucket存储类型,支持Standard、IA、Archive和ColdArchive四种存储类型。", + "example": "Standard", + "$ref": "#/components/schemas/StorageClass" + }, + "Region": { + "title": "Bucket所在地域", + "description": "Bucket所在地域。", + "type": "string", + "example": "cn-hangzhou" + } + }, + "example": "examplebucket" + }, + "BucketACL": { + "title": "The access control list (ACL) for a bucket.", + "description": "Bucket的访问权限ACL。取值范围如下:\n- public-read-write:公共读写\n- public-read:公共读\n- private(默认):私有\n\n关于Bucket访问权限ACL的更多信息,请参见[设置存储空间访问权限ACL](~~31843~~)。", + "type": "string", + "example": "private", + "default": "private", + "enum": [ + "private", + "public-read", + "public-read-write" + ] + }, + "BucketAntiDDOSConfiguration": { + "title": "A short description of struct", + "description": "保存高防实例配置信息的容器。", + "type": "object", + "properties": { + "Cnames": { + "title": "域名信息列表的容器", + "description": "保存域名信息列表的容器。", + "type": "object", + "properties": { + "Domain": { + "title": "待防护自定义域名", + "description": "待防护自定义域名。", + "type": "array", + "items": { + "description": "待防护自定义域名。每个Bucket最多支持5个待防护的自定义域名。", + "type": "string", + "example": "abc1.example.cn" + } + } + } + } + } + }, + "BucketAntiDDOSInfo": { + "title": "A short description of struct", + "description": "保存高防实例信息的容器。", + "type": "object", + "properties": { + "InstanceId": { + "title": "拥有者的UID", + "description": "高防实例ID。", + "type": "string", + "example": "cbcac8d2-4f75-4d6d-9f2e-c3447f73****" + }, + "Owner": { + "title": "拥有者的UID", + "description": "Bucket拥有者的UID。", + "type": "string", + "example": "114893010724****" + }, + "Bucket": { + "title": "高防实例ID", + "description": "防护的Bucket名称。", + "type": "string", + "example": "examplebucket" + }, + "Ctime": { + "title": "高防实例创建时间", + "description": "高防实例创建时间,格式为时间戳。", + "type": "integer", + "format": "int64", + "example": "1626769503" + }, + "Mtime": { + "title": "高防实例更新时间", + "description": "高防实例更新时间,格式为时间戳。", + "type": "integer", + "format": "int64", + "example": "1626769840" + }, + "ActiveTime": { + "title": "高防实例激活时间", + "description": "高防实例激活时间,格式为时间戳。", + "type": "integer", + "format": "int64", + "example": "1626769845" + }, + "Status": { + "title": "高防实的状态", + "description": "高防实例所处状态。\n\n- Init:初始化防护状态。\n\n- Defending:防护中状态。\n\n- HaltDefending:解除防护状态。", + "type": "string", + "example": "Defending" + }, + "Type": { + "title": "高防实的类型", + "description": "高防实例类型。固定值为AntiDDosPremimum。", + "type": "string", + "example": "AntiDDosPremimum" + }, + "Cnames": { + "title": "自定义域名容器", + "description": "保存自定义域名的容器。", + "type": "object", + "properties": { + "Domain": { + "title": "自定义域名", + "description": "自定义域名。", + "type": "array", + "items": { + "description": "自定义域名。", + "type": "string", + "example": "abc1.example.cn" + } + } + } + } + } + }, + "BucketCnameConfiguration": { + "title": "Cname配置的容器", + "description": "Cname配置的容器。", + "type": "object", + "properties": { + "Cname": { + "title": "Cname信息的容器", + "description": "Cname信息的容器。", + "type": "object", + "properties": { + "Domain": { + "title": "自定义域名", + "description": "自定义域名。", + "type": "string", + "example": "example.com" + } + } + } + } + }, + "BucketInfo": { + "title": "保存Bucket信息的容器", + "description": "保存Bucket信息的容器", + "type": "object", + "properties": { + "Bucket": { + "title": "保存Bucket信息的容器", + "description": "保存Bucket信息的容器", + "type": "object", + "properties": { + "AccessMonitor": { + "title": "Bucket是否开启访问追踪", + "description": "Bucket是否开启访问追踪", + "type": "string", + "enumValueTitles": { + "Enabled": "Enabled", + "Disabled": "Disabled" + }, + "example": "Disabled" + }, + "CreationDate": { + "title": "Bucket的创建时间", + "description": "Bucket的创建时间", + "type": "string", + "format": "iso8601", + "example": "2022-01-06T08:20:09.000Z" + }, + "CrossRegionReplication": { + "title": "Bucket是否开启跨区域复制", + "description": "Bucket是否开启跨区域复制", + "type": "string", + "enumValueTitles": { + "Enabled": "Enabled", + "Disabled": "Disabled" + }, + "example": "Disabled" + }, + "DataRedundancyType": { + "description": "Bucket的数据容灾类型", + "$ref": "#/components/schemas/DataRedundancyType" + }, + "ExtranetEndpoint": { + "title": "Bucket外网访问域名", + "description": "Bucket外网访问域名", + "$ref": "#/components/schemas/Endpoint" + }, + "IntranetEndpoint": { + "title": "Bucket内网访问域名", + "description": "Bucket内网访问域名", + "$ref": "#/components/schemas/Endpoint" + }, + "Location": { + "title": "Bucket所在地域", + "description": "Bucket所在地域", + "type": "string", + "example": "oss-cn-hangzhou" + }, + "Name": { + "title": "Bucket名称", + "description": "Bucket名称", + "type": "string", + "example": "test-bucket" + }, + "ResourceGroupId": { + "title": "Bucket所在的资源组ID", + "description": "Bucket所在的资源组ID", + "$ref": "#/components/schemas/ResourceGroupId" + }, + "StorageClass": { + "title": "Bucket的存储类型", + "description": "Bucket的存储类型", + "$ref": "#/components/schemas/StorageClass" + }, + "TransferAcceleration": { + "title": "Bucket传输", + "description": "Bucket传输", + "type": "string", + "enumValueTitles": { + "Enabled": "Enabled", + "Disabled": "Disabled" + }, + "example": "Disabled" + }, + "Versioning": { + "title": "Bucket多版本状态", + "description": "Bucket多版本状态", + "$ref": "#/components/schemas/BucketVersioningStatus" + }, + "Owner": { + "title": "Bucket所有者", + "description": "Bucket所有者", + "$ref": "#/components/schemas/Owner" + }, + "AccessControlList": { + "title": "Bucket权限", + "description": "Bucket权限", + "$ref": "#/components/schemas/AccessControlList" + }, + "ServerSideEncryptionRule": { + "title": "Bucket服务端加密配置", + "description": "Bucket服务端加密配置", + "type": "object", + "properties": { + "SSEAlgorithm": { + "title": "服务端加密类型", + "description": "设置服务器端默认加密方式。\n\n取值:KMS、AES256、SM4。", + "type": "string", + "example": "KMS" + }, + "KMSMasterKeyID": { + "title": "服务端加密KMS密钥", + "description": "服务端加密KMS密钥", + "type": "string", + "example": "\t\n9468da86-3509-4f8d-a61e-6eab1eac****" + }, + "KMSDataEncryption": { + "title": "服务端加密KMS加密算法", + "description": "指定Object的加密算法。如果未指定此选项,表明Object使用AES256加密算法。此选项仅当SSEAlgorithm取值为KMS有效。\n\n取值:SM4", + "type": "string", + "example": "SM4" + } + } + }, + "BucketPolicy": { + "title": "Bucket日志配置", + "description": "Bucket日志配置", + "$ref": "#/components/schemas/LoggingEnabled" + } + } + } + } + }, + "BucketLoggingStatus": { + "title": "A short description of struct", + "description": "存储访问日志状态信息的容器。\n", + "type": "object", + "properties": { + "LoggingEnabled": { + "description": "访问日志信息的容器。\n", + "required": true, + "$ref": "#/components/schemas/LoggingEnabled" + } + } + }, + "BucketResourceGroupConfiguration": { + "title": "Bucket资源组配置", + "description": "Bucket资源组配置", + "type": "object", + "properties": { + "ResourceGroupId": { + "title": "所属资源组ID", + "description": "所属资源组ID", + "$ref": "#/components/schemas/ResourceGroupId" + } + } + }, + "BucketStat": { + "title": "BucketStat结构的容器。", + "description": "BucketStat结构的容器。", + "type": "object", + "properties": { + "StandardStorage": { + "title": "标准存储类型的存储量,单位字节。", + "description": "标准存储类型的存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "1600" + }, + "ColdArchiveObjectCount": { + "title": "冷归档存储类型的Object数量。", + "description": "冷归档存储类型的Object数量。", + "type": "integer", + "format": "int64", + "example": "230" + }, + "ArchiveObjectCount": { + "title": "归档存储类型的Object数量。", + "description": "归档存储类型的Object数量。", + "type": "integer", + "format": "int64", + "example": "40" + }, + "InfrequentAccessStorage": { + "title": "低频存储类型的计费存储量,单位字节。", + "description": "低频存储类型的计费存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "1250" + }, + "ArchiveRealStorage": { + "title": "归档存储类型的实际存储量,单位字节。", + "description": "归档存储类型的实际存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "5990" + }, + "StandardObjectCount": { + "title": "标准存储类型的Object数量。", + "description": "标准存储类型的Object数量。", + "type": "integer", + "format": "int64", + "example": "12323" + }, + "ObjectCount": { + "title": "Bucket中总的Object数量。", + "description": "Bucket中总的Object数量。", + "type": "integer", + "format": "int64", + "example": "2034903" + }, + "Storage": { + "title": "Bucket的总存储量,单位字节。", + "description": "Bucket的总存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "39182324" + }, + "ArchiveStorage": { + "title": "归档存储类型的计费存储量,单位字节。", + "description": "归档存储类型的计费存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "30423" + }, + "LastModifiedTime": { + "title": "获取到的存储信息的时间点,格式为时间戳,单位为秒。", + "description": "获取到的存储信息的时间点,格式为时间戳,单位为秒。", + "type": "integer", + "format": "int64", + "example": "1643341269" + }, + "MultipartUploadCount": { + "title": "Bucket中已经初始化但还未完成(Complete)或者还未中止(Abort)的Multipart Upload数量。", + "description": "Bucket中已经初始化但还未完成(Complete)或者还未中止(Abort)的Multipart Upload数量。", + "type": "integer", + "format": "int64", + "example": "223" + }, + "LiveChannelCount": { + "title": "Bucket中Live Channel的数量。", + "description": "Bucket中Live Channel的数量。", + "type": "integer", + "format": "int64", + "example": "12" + }, + "ColdArchiveRealStorage": { + "title": "冷归档存储类型的实际存储量,单位字节。", + "description": "冷归档存储类型的实际存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "2312" + }, + "InfrequentAccessObjectCount": { + "title": "低频存储类型的Object数量。", + "description": "低频存储类型的Object数量。", + "type": "integer", + "format": "int64", + "example": "23" + }, + "ColdArchiveStorage": { + "title": "冷归档存储类型的计费存储量,单位字节。", + "description": "冷归档存储类型的计费存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "342" + }, + "InfrequentAccessRealStorage": { + "title": "低频存储类型的实际存储量,单位字节。", + "description": "低频存储类型的实际存储量,单位字节。", + "type": "integer", + "format": "int64", + "example": "65754" + } + } + }, + "BucketVersioningStatus": { + "description": "版本控制状态。取值如下:\n- Enabled:开启版本控制状态。\n- Suspended:暂停版本控制状态。", + "type": "string", + "example": "Enabled", + "enum": [ + "Enabled", + "Suspended" + ] + }, + "BucketWormState": { + "title": "The status of the retention policy", + "description": "合规保留策略所处的状态。\n\n可选值:\n\n- InProgress:合规保留策略创建后,该策略默认处于“InProgress”状态,且该状态的有效期为24小时。\n- Locked:合规保留策略处于锁定状态。", + "type": "string", + "example": "Locked", + "enum": [ + "InProgress", + "Locked" + ] + }, + "CORSConfiguration": { + "title": "A short description of struct", + "description": "Bucket的CORS规则容器。", + "type": "object", + "properties": { + "CORSRule": { + "title": "description", + "description": "CORS规则的容器。\n\n每个Bucket最多允许10条CORS规则。上传的XML文档最大允许16 KB。", + "type": "array", + "items": { + "description": "CORS规则的信息。", + "$ref": "#/components/schemas/CORSRule" + } + }, + "ResponseVary": { + "title": "description", + "description": "是否返回Vary: Origin头。取值范围如下:\n\n- true:不管发送的是否是跨域请求或跨域请求是否成功,均会返回Vary: Origin头。\n- false(默认值):任何情况下均不返回Vary: Origin头。\n\n> 此字段不能单独配置,必须至少配置一项跨域规则才能生效。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + } + } + }, + "CORSRule": { + "title": "A short description of struct", + "description": "CORS规则的容器。\n\n每个Bucket最多允许10条CORS规则。上传的XML文档最大允许16 KB。", + "type": "object", + "properties": { + "AllowedOrigin": { + "title": "description", + "description": "指定允许的跨域请求来源。", + "type": "array", + "items": { + "description": "指定允许的跨域请求来源。\n\nOSS允许使用多个元素来指定多个允许的来源。多个元素之间用英文逗号(,)分隔。\n\nOSS仅允许使用一个星号(\\*)通配符。如果指定为星号(\\*),则表示允许所有来源的跨域请求。", + "type": "string", + "example": "*" + } + }, + "AllowedMethod": { + "title": "description", + "description": "指定允许的跨域请求方法。", + "type": "array", + "items": { + "description": "指定允许的跨域请求方法。\n\n取值范围为GET、PUT、DELETE、POST、HEAD。", + "type": "string", + "example": "GET" + } + }, + "AllowedHeader": { + "title": "description", + "description": "控制OPTIONS预取指令Access-Control-Request-Headers中指定的Header是否被允许。在Access-Control-Request-Headers中指定的每个Header都必须在AllowedHeader中有对应的项。\n\n> 仅允许使用一个星号(*)通配符。", + "type": "string", + "example": "Authorization" + }, + "ExposeHeader": { + "title": "description", + "description": "指定允许用户从应用程序中访问的响应头。例如一个JavaScript的XMLHttpRequest对象。\n\n> 不允许使用星号(*)通配符。", + "type": "array", + "items": { + "description": "指定允许用户从应用程序中访问的响应头。例如一个JavaScript的XMLHttpRequest对象。\n\n> 不允许使用星号(*)通配符。", + "type": "string", + "example": "x-oss-test" + } + }, + "MaxAgeSeconds": { + "title": "description", + "description": "指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间。单位为秒。\n\n单条CORS规则仅允许一个MaxAgeSeconds。", + "type": "integer", + "format": "int64", + "example": "100" + } + } + }, + "CSVInput": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "FileHeaderInfo": { + "description": "指定CSV文件头信息。\n\n- Use:该CSV文件有头信息,可以用CSV列名作为Select中的列名。\n\n- Ignore:该CSV文件有头信息,但不可用CSV列名作为Select中的列名。\n\n- None:该文件没有头信息,为默认值。", + "enumValueTitles": { + "Ignore": "Ignore", + "Use": "Use", + "None": "None" + }, + "example": "Use", + "$ref": "#/components/schemas/FileHeaderInfo" + }, + "RecordDelimiter": { + "title": "description", + "description": "指定换行符,以Base64编码。默认值为\\n(可选)。未编码前的值最多为两个字符,以字符的ANSI值表示,例如在Java中使用\\n表示换行。", + "type": "string", + "example": "\\n" + }, + "FieldDelimiter": { + "title": "description", + "description": "指定CSV列分隔符,以Base64编码。默认值为`,`(可选)。未编码前的值必须为一个字符,以字符的ANSI值表示,例如在Java中使用`,`表示逗号。", + "type": "string", + "example": "," + }, + "QuoteCharacter": { + "title": "description", + "description": "指定CSV的引号字符,以Base64编码。默认值为`\\”`(可选)。在CSV中引号内的换行符,列分隔符将被视作普通字符。未编码前的值必须为一个字符,以字符的ANSI值表示,例如在Java中使用`\\”`表示引号。", + "type": "string", + "example": "\\”" + }, + "CommentCharacter": { + "title": "description", + "description": "指定CSV的注释符,以Base64编码。默认值为空(即没有注释符)。", + "type": "string", + "example": "#" + }, + "Range": { + "title": "description", + "description": "指定查询文件的范围(可选)。支持两种格式:\n\n> 使用Range参数查询的文件需要有select meta。关于select meta的更多信息,请参见[CreateSelectObjectMeta](~~74054~~)。\n\n- 按行查询:line-range=start-end。例如line-range=10-20表示扫描第10行到第20行。\n\n- 按Split查询:split-range=start-end。例如split-range=10-20表示扫描第10到第20个split。\n\n
其中start和end均为inclusive。其格式和range get中的range参数一致。\n
仅在文档是CSV或者JSON Type为LINES时使用。", + "type": "string", + "enumValueTitles": { + "line-range=start-end": "line-range=start-end", + "split-range=start-end": "split-range=start-end" + }, + "example": "line-range=start-end" + }, + "AllowQuotedRecordDelimiter": { + "title": "description", + "description": "指定CSV内容是否含有在引号中的换行符。\n
例如某一列值为`\"abc\\ndef\" `(此处`\\n`为换行), 则该值需设置为true。当该值为false时,select支持header range的语义,可以更高效的进行分片查询。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + } + } + }, + "CSVOutput": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "RecordDelimiter": { + "title": "description", + "description": "指定换行符,以Base64编码。未编码前的值最多为两个字符,以字符的ANSI值表示,例如在Java中使用`\\n`表示换行。\n
默认值:`\\n`", + "type": "string", + "example": "\\n" + }, + "FieldDelimiter": { + "title": "description", + "description": "指定CSV列分隔符,以Base64编码。未编码前的值必须为一个字符,以字符的ANSI值表示,例如在Java中使用`,`表示逗号。\n
默认值:`,`", + "type": "string", + "example": "," + } + } + }, + "CnameCertificate": { + "title": "证书信息的容器", + "description": "证书信息", + "type": "object", + "properties": { + "Type": { + "title": "证书来源", + "description": "证书来源", + "type": "string", + "enumValueTitles": { + "CAS": "证书中心", + "Upload": "旧版证书托管中用户自主上传的证书" + }, + "example": "CAS" + }, + "CertId": { + "title": "证书ID", + "description": "证书ID", + "type": "string", + "example": "493****-cn-hangzhou" + }, + "Status": { + "title": "证书状态", + "description": "证书状态", + "type": "string", + "enumValueTitles": { + "Enabled": "使用证书", + "Disabled": "未使用证书" + }, + "example": "Enabled" + }, + "CreationDate": { + "title": "证书绑定时间", + "description": "证书绑定时间", + "type": "string", + "example": "Wed, 15 Sep 2021 02:35:06 GMT" + }, + "Fingerprint": { + "title": "证书签名", + "description": "证书签名", + "type": "string", + "example": "DE:01:CF:EC:7C:A7:98:CB:D8:6E:FB:1D:97:EB:A9:64:1D:4E:**:**" + }, + "ValidStartDate": { + "title": "证书有效期起始时间", + "description": "证书有效期起始时间", + "type": "string", + "example": "Wed, 12 Apr 2023 10:14:51 GMT" + }, + "ValidEndDate": { + "title": "证书有效期终止时间", + "description": "证书有效期终止时间", + "type": "string", + "example": "Mon, 4 May 2048 10:14:51 GMT" + } + } + }, + "CnameInfo": { + "title": "A short description of struct", + "description": "Cname信息概况。", + "type": "object", + "properties": { + "Domain": { + "title": "自定义域名", + "description": "自定义域名。", + "type": "string", + "example": "example.com" + }, + "LastModified": { + "title": "绑定自定义域名的时间", + "description": "绑定自定义域名的时间。", + "type": "string", + "example": "2021-09-15T02:35:07.000Z" + }, + "Status": { + "title": "域名所处的状态", + "description": "域名所处状态。取值为:\n\n- Enabled::启用该域名。\n\n- Disabled:禁用该域名。", + "type": "string", + "example": "Enabled" + }, + "Certificate": { + "description": "证书信息的容器。", + "$ref": "#/components/schemas/CnameCertificate" + } + } + }, + "CnameSummary": { + "title": "A short description of struct", + "description": "Cname信息概况", + "type": "object", + "properties": { + "Domain": { + "title": "自定义域名", + "description": "自定义域名", + "type": "string", + "example": "example.com" + }, + "LastModified": { + "title": "绑定自定义域名的时间", + "description": "绑定自定义域名的时间", + "type": "string", + "example": "2021-09-15T02:35:07.000Z" + }, + "Status": { + "title": "域名所处的状态", + "description": "域名所处的状态", + "type": "string", + "enumValueTitles": { + "Enabled": "启用该域名", + "Disabled": "禁用该域名" + }, + "example": "Enabled" + }, + "Certificate": { + "description": "证书信息的容器", + "$ref": "#/components/schemas/CnameCertificate" + } + } + }, + "CnameToken": { + "title": "A short description of struct", + "description": "CnameToken的容器。", + "type": "object", + "properties": { + "Bucket": { + "title": "绑定Cname的Bucket名称", + "description": "绑定Cname的Bucket名称。", + "type": "string", + "example": "examplebucket" + }, + "Cname": { + "title": "绑定的Cname名称", + "description": "绑定的Cname名称。", + "type": "string", + "example": "example.com" + }, + "Token": { + "title": "Token 的内容", + "description": "OSS返回的CnameToken。", + "type": "string", + "example": "be1d49d863dea9ffeff3df7d6455****" + }, + "ExpireTime": { + "title": "Token的有效期", + "description": "CnameToken的过期时间。", + "type": "string", + "example": "Wed, 23 Feb 2022 21:16:37 GMT" + } + } + }, + "CommonPrefix": { + "title": "Objects whose names contain the same string that ranges from the prefix to the next occurrence of the delimiter are grouped as a single result", + "description": "如果请求中指定了delimiter参数,则OSS返回的响应中包含CommonPrefixes元素。该元素标明以delimiter结尾,并有共同前缀的Object名称的集合。\n", + "type": "object", + "properties": { + "Prefix": { + "title": "The prefix that the names of returned objects contain", + "description": "本次查询结果的前缀。", + "type": "string", + "example": "fun/" + } + } + }, + "CompleteMultipartUpload": { + "title": "A short description of struct", + "description": "保存CompleteMultipartUpload请求内容的容器。", + "type": "object", + "properties": { + "Part": { + "title": "The information of all parts", + "description": "保存已上传Part信息的容器。\n", + "type": "array", + "items": { + "description": "保存已上传Part信息的容器。\n", + "type": "object", + "properties": { + "PartNumber": { + "title": "Part number of the part", + "description": "Part数目。", + "type": "integer", + "format": "int64", + "example": "8" + }, + "ETag": { + "title": "The ETag of the part.", + "description": "Object生成时会创建相应的ETag ,ETag用于标识一个Object的内容。\n\n通过CompleteMultipartUpload请求创建的Object,ETag值是基于一定计算规则生成的唯一值,但不是其内容的MD5值。\n\n> ETag值可以用于检查Object内容是否发生变化。不建议使用ETag作为Object内容的MD5来校验数据完整性。", + "type": "string", + "example": "3349DC700140D7F86A0784842780****" + } + } + } + } + } + }, + "CompressionType": { + "title": "A short description of struct", + "description": "指定文件压缩类型(可选)。", + "type": "string", + "example": "None", + "enum": [ + "None", + "GZIP" + ] + }, + "CopyObjectResult": { + "title": "A short description of struct", + "description": "CopyObject的结果。", + "type": "object", + "properties": { + "ETag": { + "title": "description", + "description": "Object生成时会创建相应的ETag ,ETag用于标识一个Object的内容。\n - 对于PutObject请求创建的Object,ETag值是其内容的MD5值。\n - 对于其他方式创建的Object,ETag值是基于一定计算规则生成的唯一值,但不是其内容的MD5值。\n\n>ETag值可以用于检查Object内容是否发生变化。不建议使用ETag作为Object内容的MD5来校验数据完整性。\n默认值:无", + "type": "string", + "example": "\t\n5B3C1A2E053D763E1B002CC607C5****" + }, + "LastModified": { + "title": "description", + "description": "最近一次修改的时间。\n", + "type": "string", + "example": "Fri, 24 Feb 2012 07:18:48 GMT" + } + } + }, + "CopyPartResult": { + "title": "A short description of struct", + "description": "CopyObject的结果。", + "type": "object", + "properties": { + "ETag": { + "title": "A short description of ETag", + "description": "Object生成时会创建相应的ETag ,ETag用于标识一个Object的内容。\n通过CompleteMultipartUpload请求创建的Object,ETag值是基于一定计算规则生成的唯一值,但不是其内容的MD5值。\n\n> ETag值可以用于检查Object内容是否发生变化。不建议使用ETag作为Object内容的MD5来校验数据完整性。\n", + "type": "string", + "example": "3349DC700140D7F86A0784842780****" + }, + "LastModified": { + "title": "A short description of LastModified", + "description": "Part上传的时间。", + "type": "string", + "format": "iso8601", + "example": "2012-02-23T07:01:34.000Z" + } + } + }, + "CreateAccessPointConfiguration": { + "title": "保存接入点信息的容器。", + "description": "保存接入点信息的容器。", + "type": "object", + "properties": { + "AccessPointName": { + "title": "接入点名称", + "description": "接入点名称。接入点命名规范如下:\n\n- 接入点名称在当前阿里云账号单个地域内唯一。\n\n- 不允许以-ossalias结尾。\n\n- 只能包括小写字母、数字和短划线(-),不能以短划线(-)开头或结尾。\n\n- 命名长度为3~19个字符。", + "type": "string", + "example": "ap-01" + }, + "NetworkOrigin": { + "title": "接入点网络来源。", + "description": "接入点网络来源。", + "$ref": "#/components/schemas/AccessPointNetworkOrigin" + }, + "VpcConfiguration": { + "title": "保存VPC网络来源信息的容器。", + "description": "保存VPC网络来源信息的容器。", + "$ref": "#/components/schemas/AccessPointVpcConfiguration" + } + } + }, + "CreateAccessPointResult": { + "title": "保存接入点信息的容器。", + "description": "保存接入点信息的容器。", + "type": "object", + "properties": { + "AccessPointArn": { + "title": "接入点ARN。", + "description": "接入点ARN。", + "$ref": "#/components/schemas/AccessPointArn" + }, + "Alias": { + "title": "接入点别名。", + "description": "接入点别名。", + "$ref": "#/components/schemas/AccessPointAlias" + } + } + }, + "CreateBucketConfiguration": { + "title": "The configuration of a bucket.", + "description": "Bucket存储类型和数据容灾类型的配置信息。", + "type": "object", + "properties": { + "StorageClass": { + "description": "Bucket的存储类型。 取值范围如下:\n\n- Standard(默认):标准存储\n- IA:低频访问\n- Archive:归档存储\n- ColdArchive:冷归档存储", + "enumValueTitles": {}, + "$ref": "#/components/schemas/StorageClass" + }, + "DataRedundancyType": { + "description": "指定Bucket的数据容灾类型。\n\n- LRS(默认值)\n
本地冗余LRS,将您的数据冗余存储在同一个可用区的不同存储设备上,可支持两个存储设备并发损坏时,仍维持数据不丢失,可正常访问。\n\n- ZRS\n
同城冗余ZRS采用多可用区(AZ)机制,将您的数据冗余存储在同一地域(Region)的3个可用区。可支持单个可用区(机房)整体故障时(例如断电、火灾等),仍然能够保障数据的正常访问。\n> 归档类型的Bucket不支持设置同城冗余。", + "enumValueTitles": {}, + "$ref": "#/components/schemas/DataRedundancyType" + } + } + }, + "CreateSelectMetaProcess": { + "description": "CreateSelectMeta可选的x-oss-process参数", + "type": "string", + "example": "csv/meta" + }, + "DataRedundancyType": { + "title": "The type of disaster recovery for a bucket.", + "description": "Bucket的数据容灾类型。取值范围如下:\n\n- LRS(默认) :本地冗余LRS,将您的数据冗余存储在同一个可用区的不同存储设备上,可支持两个存储设备并发损坏时,仍维持数据不丢失,可正常访问。\n- ZRS:同城冗余ZRS,采用多可用区(AZ)机制,将您的数据冗余存储在同一地域(Region)的3个可用区。可支持单个可用区(机房)整体故障时(例如断电、火灾等),仍然能够保障数据的正常访问。\n>归档类型的Bucket不支持设置同城冗余。", + "type": "string", + "example": "LRS", + "default": "LRS", + "enum": [ + "LRS", + "ZRS" + ] + }, + "Delete": { + "title": "A short description of struct", + "description": "保存DeleteMultipleObjects请求的容器。", + "type": "object", + "properties": { + "Quiet": { + "title": "description", + "description": "打开简单响应模式的开关。\nDeleteMultipleObjects提供以下两种消息返回模式:\n - 简单模式(quiet):OSS不返回消息体。\n - 详细模式(verbose):OSS返回的消息体中会包含所有删除Object的结果。默认采用详细模式。\n\n有效值:**true**(开启简单模式)、**false**(开启详细模式)\n默认值:**false**\n", + "type": "boolean", + "example": "false" + }, + "Object": { + "title": "description", + "description": "保存一个Object信息的容器。", + "type": "array", + "items": { + "description": "对象标识符。", + "$ref": "#/components/schemas/ObjectIdentifier" + } + } + } + }, + "DeleteMarkerEntry": { + "title": "Information about the delete marker", + "description": "保存删除标记的容器。\n\n", + "type": "object", + "properties": { + "Key": { + "title": "The name of the object", + "description": "Object的名称。", + "type": "string", + "example": "example" + }, + "VersionId": { + "title": "The version ID of the object", + "description": "Object的版本ID。\n", + "type": "string", + "example": "CAEQMxiBgMDNoP2D0BYiIDE3MWUxNzgxZDQxNTRiODI5OGYwZGMwNGY3MzZjN****" + }, + "IsLatest": { + "title": "Indicates whether the version is the current version", + "description": "Object是否为当前版本。\n取值:\n\n- true:Object为当前版本。\n\n- false:Object为非当前版本。\n", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true", + "default": "false" + }, + "LastModified": { + "title": "The last modified time of the object", + "description": "Object最后被修改的时间。", + "type": "string", + "format": "iso8601", + "example": "2019-04-09T07:27:28.000Z" + }, + "Owner": { + "description": "保存Bucket拥有者信息的容器。", + "$ref": "#/components/schemas/Owner" + } + } + }, + "DeletedObject": { + "title": "A short description of struct", + "description": "保存被成功删除的Object的容器。\n\n", + "type": "object", + "properties": { + "Key": { + "title": "description", + "description": "被删除Object的名字。", + "type": "string", + "example": "multipart.data" + }, + "DeleteMarker": { + "title": "description", + "description": "表示该版本是否为删除标记。true为是,false为否。\n> 只有当创建删除标记和永久删除删除标记时,才会返回该元素,且值为true。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + }, + "DeleteMarkerVersionId": { + "title": "description", + "description": "表示删除标记对应的版本ID。", + "type": "string", + "example": "CAEQMhiBgIDB3aWB0BYiIGUzYTA3YzliMzVmNzRkZGM5NjllYTVlMjYyYWEy****" + }, + "VersionId": { + "title": "description", + "description": "Object对应的版本ID。", + "type": "string", + "example": "CAEQNRiBgIDyz.6C0BYiIGQ2NWEwNmVhNTA3ZTQ3MzM5ODliYjM1ZTdjYjA4****" + } + } + }, + "EncodeType": { + "title": "specifies the encoding method to use", + "description": "指明返回结果中编码使用的类型。如果请求的参数中指定了encoding-type,那返回的结果会对Key进行编码。\n", + "type": "string", + "example": "URL", + "enum": [ + "url" + ] + }, + "Endpoint": { + "title": "访问域名", + "description": "访问域名", + "type": "string", + "example": "oss-cn-hangzhou.aliyuncs.com" + }, + "Error": { + "title": "Error responses", + "description": "错误响应。", + "type": "object", + "properties": { + "Code": { + "title": "The error code that OSS returns to the user", + "description": "错误码。", + "type": "string", + "example": "AccessDenied" + }, + "Message": { + "title": "The detailed error message provided by OSS", + "description": "错误信息。", + "type": "string", + "example": "Anonymous user has no right to access this bucket." + }, + "RequestId": { + "title": "The ID that uniquely identifies a request", + "description": "请求ID。", + "type": "string", + "example": "654D97A16F8C26383287EAAF" + }, + "HostId": { + "title": "The ID of the host in the accessed OSS cluster", + "description": "访问OSS所用的域名。", + "type": "string", + "example": "example-bucket.oss-cn-hangzhou.aliyuncs.com" + } + } + }, + "ErrorDocument": { + "title": "A short description of struct", + "description": "404页面的容器。", + "type": "object", + "properties": { + "Key": { + "title": "description", + "description": "错误页面。\n", + "type": "string", + "example": "error.html" + }, + "HttpStatus": { + "title": "description", + "description": "返回错误页面时的HTTP状态码。\n", + "type": "string", + "example": "404" + } + } + }, + "ExtendWormConfiguration": { + "title": "The configuration of extending the retention period of objects in a bucket", + "description": "根节点。", + "type": "object", + "properties": { + "RetentionPeriodInDays": { + "title": "The number of days for which objects can be retained", + "description": "指定Object的保留天数。", + "type": "integer", + "format": "int32", + "example": "366" + } + } + }, + "FileHeaderInfo": { + "title": "A short description of struct", + "description": "指定CSV文件头信息(可选)。\n取值:\n - Use:该CSV文件有头信息,可以用CSV列名作为Select中的列名。\n - Ignore:该CSV文件有头信息,但不可用CSV列名作为Select中的列名。\n - None:该文件没有头信息,为默认值。\n\n", + "type": "string", + "example": "Use", + "enum": [ + "USE", + "IGNORE", + "NONE" + ] + }, + "GetAccessPointResult": { + "title": "保存接入点信息的容器。", + "description": "保存接入点信息的容器。", + "type": "object", + "properties": { + "AccessPointName": { + "description": "接入点名称。", + "$ref": "#/components/schemas/AccessPointName" + }, + "Bucket": { + "title": "配置接入点的Bucket名称。", + "description": "配置接入点的Bucket名称。", + "type": "string", + "example": "example-bucket" + }, + "AccountId": { + "title": "配置接入点的阿里云账号UID。", + "description": "配置接入点的阿里云账号UID。", + "type": "string", + "example": "10378****8768" + }, + "NetworkOrigin": { + "title": "接入点网络来源。返回值如下: vpc:限制仅支持通过指定的VPC ID访问接入点。 internet:同时持通过外网和内网Endpoint互联网访问接入点。", + "description": "接入点网络来源。返回值如下: vpc:限制仅支持通过指定的VPC ID访问接入点。 internet:同时持通过外网和内网Endpoint互联网访问接入点。", + "$ref": "#/components/schemas/AccessPointNetworkOrigin" + }, + "VpcConfiguration": { + "title": "保存VPC网络来源信息的容器。", + "description": "保存VPC网络来源信息的容器。", + "$ref": "#/components/schemas/AccessPointVpcConfiguration" + }, + "AccessPointArn": { + "description": "接入点ARN。", + "$ref": "#/components/schemas/AccessPointArn" + }, + "Alias": { + "description": "接入点别名。", + "$ref": "#/components/schemas/AccessPointAlias" + }, + "Status": { + "description": "接入点所处状态。", + "$ref": "#/components/schemas/AccessPointStatus" + }, + "Endpoints": { + "title": "保存接入点网络来源信息的容器。", + "description": "保存接入点网络来源信息的容器。", + "type": "object", + "properties": { + "PublicEndpoint": { + "title": "接入点的外网Endpoint。", + "description": "接入点的外网Endpoint。", + "$ref": "#/components/schemas/Endpoint" + } + } + }, + "InternalEndpoint": { + "title": "接入点的内网Endpoint。", + "description": "接入点的内网Endpoint。", + "$ref": "#/components/schemas/Endpoint" + } + } + }, + "Grant": { + "description": "Bucket的读写权限ACL。\n\n", + "$ref": "#/components/schemas/ObjectACL" + }, + "HttpsConfiguration": { + "title": "存储空间安全传输层配置", + "description": "存储空间TLS版本配置", + "type": "object", + "properties": { + "TLS": { + "title": "存储空间TLS版本配置", + "description": "存储空间TLS版本配置", + "type": "object", + "properties": { + "Enable": { + "title": "是否启用TLS版本配置", + "description": "是否启用TLS版本配置", + "type": "boolean", + "required": true, + "enumValueTitles": { + "true": "开启TLS版本设置", + "false": "关闭TLS版本设置" + }, + "example": "true" + }, + "TLSVersion": { + "title": "TLS版本列表", + "description": "TLS版本列表", + "type": "array", + "items": { + "description": "TLS版本", + "type": "string", + "enumValueTitles": { + "TLSv1.3": "TLSv1.3", + "TLSv1.2": "TLSv1.2", + "TLSv1.1": "TLSv1.1", + "TLSv1.0": "TLSv1.0" + }, + "example": "TLSv1.2" + } + } + } + } + } + }, + "IndexDocument": { + "title": "A short description of struct", + "description": "默认主页的容器。\n\n", + "type": "object", + "properties": { + "Suffix": { + "title": "description", + "description": "默认主页。", + "type": "string", + "example": "index.html" + }, + "SupportSubDir": { + "title": "description", + "description": "访问子目录时,是否支持转到子目录下的默认主页。取值范围如下:\n - **true**:转到子目录下的默认主页。\n - **false**(默认):不转到子目录下的默认主页,而是转到根目录下的默认主页。\n\n假设默认主页为index.html,要访问`bucket.oss-cn-hangzhou.aliyuncs.com/subdir/`,如果设置**SupportSubDir**为false,则转到`bucket.oss-cn-hangzhou.aliyuncs.com/index.html`;如果设置**SupportSubDir**为true,则转到`bucket.oss-cn-hangzhou.aliyuncs.com/subdir/index.html`。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "Type": { + "title": "description", + "description": "设置默认主页后,访问以非正斜线(/)结尾的Object,且该Object不存在时的行为。 只有设置**SupportSubDir**为true时才生效,且生效的顺序在RoutingRule之后、ErrorFile之前。\n假设默认主页为index.html,要访问的文件路径为`bucket.oss-cn-hangzhou.aliyuncs.com/abc`,且abc这个Object不存在,此时**Type**的不同取值对应的行为如下:\n - **0**(默认):检查abc/index.html是否存在(即`Object + 正斜线(/)+ 主页`的形式),如果存在则返回302,Location头为`/abc/`的URL编码(即`正斜线(/) + Object + 正斜线(/)`的形式),如果不存在则返回404,继续检查ErrorFile。\n - **1**:直接返回404,报错NoSuchKey,继续检查ErrorFile。\n - **2**:检查abc/index.html是否存在,如果存在则返回该Object的内容;如果不存在则返回404,继续检查ErrorFile。\n\n", + "type": "string", + "example": "0" + } + } + }, + "InitiateWormConfiguration": { + "title": "The confiiguration of a retention policy", + "description": "根节点。", + "type": "object", + "properties": { + "RetentionPeriodInDays": { + "title": "The number of days for which objects can be retained", + "description": "指定Object保留天数。", + "type": "integer", + "format": "int32", + "required": true, + "example": "365" + } + } + }, + "InputSerialization": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "CompressionType": { + "description": "指定文件压缩类型(可选)。目前不支持任何压缩,即取值只能是None。", + "example": "None", + "$ref": "#/components/schemas/CompressionType" + }, + "CSV": { + "description": "指定CSV输入格式。", + "$ref": "#/components/schemas/CSVInput" + }, + "JSON": { + "description": "指定JSON输入格式。", + "$ref": "#/components/schemas/JSONInput" + } + } + }, + "InventoryConfiguration": { + "title": "The configuration of a inventory task", + "description": "存储清单配置信息的容器。\n\n", + "type": "object", + "properties": { + "Id": { + "title": "The specified inventory list name, which must be globally unique in the bucket", + "description": "自定义清单名称,清单名称在当前Bucket下必须唯一。", + "type": "string", + "example": "report1" + }, + "IsEnabled": { + "title": "Indicates whether the inventory function is enabled", + "description": "是否启用清单功能。取值范围如下:\n\n- true:启用清单功能。\n- false:不启用清单功能。\n", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + }, + "Destination": { + "description": "存放清单结果。", + "$ref": "#/components/schemas/InventoryDestination" + }, + "Schedule": { + "description": "存放清单导出周期信息的容器。", + "$ref": "#/components/schemas/InventorySchedule" + }, + "Filter": { + "description": "清单筛选的前缀。指定前缀后,清单将筛选出符合前缀设置的对象。", + "$ref": "#/components/schemas/InventoryFilter" + }, + "IncludedObjectVersions": { + "description": "是否在清单中包含Object版本信息。\n取值范围如下:\n\n- All:导出Object的所有版本信息。\n\n- Current:导出Object的当前版本信息。\n", + "enumValueTitles": { + "All": "All", + "Current": "Current" + }, + "example": "All", + "$ref": "#/components/schemas/InventoryIncludedObjectVersions" + }, + "OptionalFields": { + "title": "The container that stores the configuration fields included in the inventory list", + "description": "清单结果中包含的配置项列表。", + "type": "object", + "properties": { + "Field": { + "title": "field list", + "description": "清单结果中包含的配置项。\n可选的配置项包括:\n\n- Size:Object的大小。\n- LastModifiedDate:Object的最后修改时间。\n- ETag:Object的ETag值,用于标识Object的内容。\n- StorageClass:Object的存储类型。\n- IsMultipartUploaded:是否为通过分片上传方式上传的Object。\n- EncryptionStatus:Object是否加密。\n\n", + "type": "array", + "items": { + "description": "清单结果中包含的配置项。", + "$ref": "#/components/schemas/InventoryOptionalField" + } + } + } + } + } + }, + "InventoryDestination": { + "title": "The information about the bucket that stores the exported inventory list", + "description": "存放清单结果的信息。", + "type": "object", + "properties": { + "OSSBucketDestination": { + "title": "The information about the bucket that stores the exported inventory list", + "description": "清单结果导出后存放的Bucket信息。", + "$ref": "#/components/schemas/InventoryOSSBucketDestination" + } + } + }, + "InventoryEncryption": { + "title": "The container that stores the encryption method of the inventory list", + "description": "清单文件的加密方式。", + "type": "object", + "properties": { + "SSE-OSS": { + "title": "The container that stores the information about the SSE-OSS encryption method", + "description": "保存SSE-OSS加密方式的容器。", + "$ref": "#/components/schemas/SSEOSS" + }, + "SSE-KMS": { + "title": "The container that stores the CMK used in the SSE-KMS encryption method", + "description": "保存SSE-KMS加密密钥的容器。", + "$ref": "#/components/schemas/SSEKMS" + } + } + }, + "InventoryFilter": { + "title": "Contains the prefix used to filter the objects in the inventory list", + "description": "清单筛选的前缀。指定前缀后,清单将筛选出符合前缀设置的对象。", + "type": "object", + "properties": { + "Prefix": { + "title": "The prefix specified in the inventory rule", + "description": "筛选规则的匹配前缀。", + "type": "string", + "example": "Pics/" + } + } + }, + "InventoryFormat": { + "title": "The format of the exported inventory list", + "description": "取值范围为CSV。", + "type": "string", + "example": "CSV", + "enum": [ + "CSV" + ] + }, + "InventoryFrequency": { + "title": "The frequency that inventory lists are exported", + "description": "清单文件导出的周期。\n\n有效值:\n- Daily:按天导出清单文件。\n- Weekly:按周导出清单文件。", + "type": "string", + "enumValueTitles": { + "Daily": "Daily", + "Weekly": "Weekly" + }, + "example": "Daily", + "enum": [ + "Daily", + "Weekly" + ] + }, + "InventoryIncludedObjectVersions": { + "title": "Specifies whether versioning information about the objects is included in the inventory list", + "description": "是否在清单中包含Object版本信息。取值范围如下:\n\n- All:导出Object的所有版本信息。\n- Current:导出Object的当前版本信息。", + "type": "string", + "enumValueTitles": { + "All": "All", + "Current": "Current" + }, + "example": "All", + "enum": [ + "All", + "Current" + ] + }, + "InventoryOSSBucketDestination": { + "title": "The information about the bucket that stores the exported inventory list", + "description": "清单结果导出后存放的Bucket信息。\n", + "type": "object", + "properties": { + "Format": { + "description": "清单文件的文件格式。 清单文件导出后的格式为使用GZIP压缩的CSV文件。", + "$ref": "#/components/schemas/InventoryFormat" + }, + "AccountId": { + "title": "The account ID granted by the bucket owner", + "description": "Bucket所有者授予的账户ID。", + "type": "string", + "example": "100000000000000" + }, + "RoleArn": { + "title": "The name of the role to which the bucket owner grants permissions", + "description": "具有读取源Bucket所有文件和向目标Bucket写入文件权限的角色名,格式为`acs:ram::uid:role/rolename`。", + "type": "string", + "example": "acs:ram::100000000000000:role/AliyunOSSRole" + }, + "Bucket": { + "title": "The bucket that stores the exported inventory list", + "description": "存放导出的清单文件的Bucket。\n", + "type": "string", + "example": "acs:oss:::bucket_0001" + }, + "Prefix": { + "title": "The path of the exported inventory list", + "description": "清单文件的存储路径前缀。", + "type": "string", + "example": "prefix1/" + }, + "Encryption": { + "description": "清单文件的加密方式。", + "$ref": "#/components/schemas/InventoryEncryption" + } + } + }, + "InventoryOptionalField": { + "title": "The configuration fields included in the inventory list", + "description": "清单结果中包含的配置项。\n\n- Size:Object的大小。\n- LastModifiedDate:Object的最后修改时间。\n- ETag:Object的ETag值,用于标识Object的内容。\n- StorageClass:Object的存储类型。\n- IsMultipartUploaded:是否为通过分片上传方式上传的Object。\n- EncryptionStatus:Object是否加密。", + "type": "string", + "example": "Size", + "enum": [ + "Size", + "LastModifiedDate", + "ETag", + "StorageClass", + "IsMultipartUploaded", + "EncryptionStatus" + ] + }, + "InventorySchedule": { + "title": "Contains the frequency that inventory lists are exported", + "description": "Contains the frequency that inventory lists are exported", + "type": "object", + "properties": { + "Frequency": { + "$ref": "#/components/schemas/InventoryFrequency" + } + } + }, + "JSONInput": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "Type": { + "description": "指定输入JSON的类型。", + "enumValueTitles": { + " LINES": " LINES", + "DOCUMENT": "DOCUMENT" + }, + "example": "DOCUMENT", + "$ref": "#/components/schemas/JSONType" + }, + "Range": { + "title": "description", + "description": "指定查询文件的范围(可选)。支持两种格式:\n> 使用Range参数查询的文件需要有select meta。关于select meta的更多信息,请参见[CreateSelectObjectMeta](~~74054~~)。\n\n- 按行查询:line-range=start-end。例如line-range=10-20表示扫描第10行到第20行。\n\n- 按Split查询:split-range=start-end。例如split-range=10-20表示扫描第10到第20个split。\n\n
其中start和end均为inclusive。其格式和range get中的range参数一致。\n
仅在文档是CSV或者JSON Type为LINES时使用。", + "type": "string", + "enumValueTitles": { + "line-range=start-end": "line-range=start-end", + "split-range=start-end": "split-range=start-end" + }, + "example": "line-range=start-end" + }, + "ParseJsonNumberAsString": { + "title": "description", + "description": "将JSON中的数字(整数和浮点数)解析成字符串。目前JSON中的浮点数解析时会损失精度,如果要完整保留原始数据,则推荐用该选项。如果需要进行数值计算,则可以在SQL中cast成需要的格式,例如int、double、decimal。\n
默认值: false", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + } + } + }, + "JSONOutput": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "RecordDelimiter": { + "title": "description", + "description": "指定换行符,以Base64编码。未编码前的值最多为两个字符,以字符的ANSI值表示,例如在Java中使用`\\n`表示换行。\n
默认值:`\\n`", + "type": "string", + "example": "\\n" + } + } + }, + "JSONType": { + "title": "A short description of struct", + "description": "指定输入JSON的类型。\n取值:\n- DOCUMENT:输入数据中的单个JSON对象可以跨行。\n- LINES:输入数据中的每一行都包含一个JSON对象。", + "type": "string", + "enumValueTitles": { + "DOCUMENT": "DOCUMENT", + "LINES": "LINES" + }, + "example": "DOCUMENT", + "enum": [ + "DOCUMENT", + "LINES" + ] + }, + "LifecycleConfiguration": { + "title": "A short description of struct", + "description": "Lifecycle配置的容器,最多可容纳1000条规则。", + "type": "object", + "properties": { + "Rule": { + "title": "description", + "description": "生命周期规则的容器。Object设置过期时间必须大于转储为IA或者Archive存储类型的时间。\n", + "type": "array", + "items": { + "description": "生命周期规则的容器。Object设置过期时间必须大于转储为IA或者Archive存储类型的时间。\n", + "$ref": "#/components/schemas/LifecycleRule" + } + } + } + }, + "LifecycleRule": { + "title": "生命周期规则", + "description": "生命周期规则的容器。\n - 不支持Archive Bucket创建转储规则。\n - Object设置过期时间必须大于转储为IA或者Archive存储类型的时间。\n\n", + "type": "object", + "properties": { + "ID": { + "title": "规则标识", + "description": "标识规则的唯一ID。最多由255个字节组成。如没有指定,或者该值为空时,OSS会自动生成一个唯一ID。\n", + "type": "string", + "required": true, + "example": "rule1" + }, + "Prefix": { + "title": "指定规则所适用的前缀", + "description": "指定规则所适用的前缀(Prefix)。Prefix不可重复。\n - 若指定了Prefix,则表示此规则仅适用于Bucket中与Prefix匹配的Object。\n - 若Prefix置空,则表示此规则适用于Bucket中的所有Object。", + "type": "string", + "required": false, + "example": "tmp/" + }, + "Status": { + "title": "规则的状态", + "description": "是否启用规则。取值范围如下:\n- Enabled:表示启用规则,OSS会定期执行该规则。\n- Disabled:表示不启用规则,OSS会忽略该规则。", + "type": "string", + "required": true, + "enumValueTitles": { + "Enabled": "Enabled", + "Disabled": "Disabled" + }, + "example": "Enabled" + }, + "Expiration": { + "title": "过期属性", + "description": "指定Object生命周期规则的过期属性。 对于受版本控制的Bucket,指定的过期属性只对Object的当前版本生效。\n
Object的过期时间必须大于转储为IA或Archive类型的时间。", + "type": "object", + "properties": { + "CreatedBeforeDate": { + "title": "日期", + "description": "指定一个日期,OSS会对最后更新时间早于该日期的数据执行生命周期规则。日期格式为yyyy-MM-ddT00:00:00.000Z。\n
日期需要按照ISO8601标准表示并使用UTC时间,且必须为UTC的零点。", + "type": "string", + "format": "iso8601", + "example": "2002-10-11T00:00:00.000Z" + }, + "Days": { + "title": "天数", + "description": "指定生命周期规则在距离Object最后更新多少天后生效。", + "type": "integer", + "format": "int32", + "example": "1" + }, + "ExpiredObjectDeleteMarker": { + "title": "自动移除过期删除标记", + "description": "指定是否自动移除过期删除标记。\n\n- true:表示自动移除过期删除标记。取值为true时,不支持指定Days或CreatedBeforeDate。\n\n- false:表示不会自动移除过期删除标记。取值为false时,则必须指定Days或CreatedBeforeDate。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + } + } + }, + "Transition": { + "title": "存储类型转换", + "description": "指定Object在有效生命周期中,OSS何时将Object转储为IA、Archive和ColdArchive存储类型 。\nStandard Bucket中的Standard Object可以转储为IA、Archive或ColdArchive存储类型,但转储Archive存储类型的时间必须比转储IA存储类型的时间长。例如Transition\nIA设置Days为30,Transition Archive设置Days必须大于30。\n\n> Days或CreatedBeforeDate只能二选一。\n\n", + "type": "array", + "items": { + "description": "指定Object在有效生命周期中,OSS何时将Object转储为IA、Archive和ColdArchive存储类型 。\nStandard Bucket中的Standard Object可以转储为IA、Archive或ColdArchive存储类型,但转储Archive存储类型的时间必须比转储IA存储类型的时间长。例如Transition\nIA设置Days为30,Transition Archive设置Days必须大于30。\n\n> Days或CreatedBeforeDate只能二选一。\n\n", + "type": "object", + "properties": { + "CreatedBeforeDate": { + "title": "日期", + "description": "指定一个日期,OSS会对最后更新时间早于该日期的数据执行生命周期规则。日期必须服从ISO8601的格式,且要求是UTC的零点。\n", + "type": "string", + "format": "iso8601", + "example": "2002-10-11T00:00:00.000Z" + }, + "Days": { + "title": "天数", + "description": "指定生命周期规则在距离Object最后更新多少天后生效。\n", + "type": "integer", + "format": "int32", + "example": "1" + }, + "StorageClass": { + "description": "指定Object转储的存储类型。\n\n- IA:低频访问\n- Archive:归档存储\n- ColdArchive:冷归档存储\n\n> IA Bucket中的Object可以转储为Archive或者ColdArchive存储类型,但不支持转储为Standard存储类型。\n", + "enumValueTitles": {}, + "$ref": "#/components/schemas/StorageClass" + }, + "IsAccessTime": { + "title": "基于最后访问时间", + "description": "指定是否基于last access time匹配规则。取值如下:\n\n- true:采用Object的last access time(最后一次访问时间)匹配规则。\n\n- false(默认值):采用Object的last modify time(最后一次修改时间)匹配规则。", + "type": "boolean", + "example": "true" + }, + "ReturnToStdWhenVisit": { + "title": "再次访问是否转回标准存储", + "description": "指定Object转为非标准存储后,再次访问时是否将Object转为标准存储。只有当IsAccessTime设置为true时才有效。取值如下:\n\n- true:Object由非标准存储转为标准存储。\n\n- false(默认值):Object仍为非标准存储。", + "type": "boolean", + "example": "true" + }, + "AllowSmallFile": { + "title": "小文件是否转储", + "description": "基于最后一次访问时间设置生命周期规则时,指定是否将小于64 KB的Object转储为低频、归档、冷归档文件类型。取值如下:\n\n- true(默认值):转储包含小于64 KB在内的所有Object。当Object小于64 KB时,按照64 KB计算。当Object大于或等于64 KB时,按照实际大小计算。设置为true时,可能会增加存储费用。\n\n- false:不转储小于64 KB的Object。", + "type": "boolean", + "example": "true" + } + } + } + }, + "AbortMultipartUpload": { + "title": "未完成分片上传的过期属性", + "description": "指定未完成分片上传的过期属性。\n", + "type": "object", + "properties": { + "Days": { + "title": "天数", + "description": "指定生命周期规则在距离Object最后更新多少天后生效。\n", + "type": "integer", + "format": "int32", + "example": "1" + }, + "CreatedBeforeDate": { + "title": "日期", + "description": "指定一个日期,OSS会对最后更新时间早于该日期的数据执行生命周期规则。日期必须服从ISO8601的格式,且要求是UTC的零点。\n", + "type": "string", + "format": "iso8601", + "example": "2002-10-11T00:00:00.000Z" + } + } + }, + "Tag": { + "title": "标签列表", + "description": "指定规则所适用的对象标签,可设置多个。\n", + "type": "array", + "items": { + "description": "指定规则所适用的对象标签,可设置多个。\n", + "$ref": "#/components/schemas/Tag" + } + }, + "NoncurrentVersionExpiration": { + "title": "非当前版本生命周期规则的过期属性", + "description": "指定Object非当前版本生命周期规则的过期属性。\n", + "type": "object", + "properties": { + "NoncurrentDays": { + "title": "天数", + "description": "指定生命周期规则在Object成为非当前版本多少天后生效。\n", + "type": "integer", + "format": "int32", + "example": "5" + } + } + }, + "NoncurrentVersionTransition": { + "title": "非当前版本生命周期规则的转储属性", + "description": "在有效的生命周期规则中,OSS何时将指定Object的非当前版本转储为IA或者Archive存储类型 。\nStandard类型的Object转储为Archive类型的时间必须大于转储为IA类型的时间。\n", + "type": "array", + "items": { + "description": "在有效的生命周期规则中,OSS何时将指定Object的非当前版本转储为IA或者Archive存储类型 。\nStandard类型的Object转储为Archive类型的时间必须大于转储为IA类型的时间。\n", + "type": "object", + "properties": { + "NoncurrentDays": { + "title": "天数", + "description": "指定生命周期规则在Object成为非当前版本多少天后生效。\n", + "type": "integer", + "format": "int32", + "example": "5" + }, + "StorageClass": { + "title": "存储类型", + "description": "指定Object转储的存储类型。\n\n- IA:低频访问\n- Archive:归档存储\n- ColdArchive:冷归档存储\n\n> IA Bucket中的Object可以转储为Archive或者ColdArchive存储类型,但不支持转储为Standard存储类型。\n", + "enumValueTitles": {}, + "$ref": "#/components/schemas/StorageClass" + }, + "IsAccessTime": { + "title": "基于最后访问时间", + "description": "指定是否基于last access time匹配规则。取值如下:\n\n- true:采用Object的last access time(最后一次访问时间)匹配规则。\n\n- false(默认值):采用Object的last modify time(最后一次修改时间)匹配规则。", + "type": "boolean", + "example": "true" + }, + "ReturnToStdWhenVisit": { + "title": "再次访问是否转回标准存储", + "description": "指定Object转为非标准存储后,再次访问时是否将Object转为标准存储。只有当IsAccessTime设置为true时才有效。取值如下:\n\n- true:Object由非标准存储转为标准存储。\n\n- false(默认值):Object仍为非标准存储。", + "type": "boolean", + "example": "true" + }, + "AllowSmallFile": { + "title": "小文件是否转储", + "description": "基于最后一次访问时间设置生命周期规则时,指定是否将小于64 KB的Object转储为低频、归档、冷归档文件类型。取值如下:\n\n- true(默认值):转储包含小于64 KB在内的所有Object。当Object小于64 KB时,按照64 KB计算。当Object大于或等于64 KB时,按照实际大小计算。设置为true时,可能会增加存储费用。\n\n- false:不转储小于64 KB的Object。", + "type": "boolean", + "example": "true" + } + } + } + }, + "Filter": { + "title": "本条规则的排除条件", + "description": "本条规则的排除条件。", + "type": "object", + "properties": { + "Not": { + "title": "满足何种规则跳过", + "description": "满足何种规则跳过。", + "type": "object", + "properties": { + "Prefix": { + "title": "排除规则适用的前缀", + "description": "排除规则适用的前缀。", + "type": "string", + "example": "tmp/not/" + }, + "Tag": { + "title": "排除规则适用的标签", + "description": "排除规则适用的标签。", + "$ref": "#/components/schemas/Tag" + } + } + } + } + } + } + }, + "ListAccessPointsResult": { + "title": "保存本次列举接入点信息结果的容器。", + "description": "保存本次列举接入点信息结果的容器。", + "type": "object", + "properties": { + "IsTruncated": { + "title": "请求中返回的结果是否被截断。返回值如下: true:表示本次未返回全部结果。 false:表示本次已返回全部结果。", + "description": "请求中返回的结果是否被截断。返回值如下: true:表示本次未返回全部结果。 false:表示本次已返回全部结果。", + "type": "string", + "example": "true" + }, + "NextContinuationToken": { + "title": "表明本次ListAccessPoints请求包含后续结果,需要将NextContinuationToken指定为continuation-token继续获取结果。", + "description": "表明本次ListAccessPoints请求包含后续结果,需要将NextContinuationToken指定为continuation-token继续获取结果。", + "type": "string", + "example": "abc**" + }, + "AccountId": { + "title": "接入点所属的阿里云账号UID。", + "description": "接入点所属的阿里云账号UID。", + "type": "string", + "example": "10107***1448150" + }, + "AccessPoints": { + "title": "保存所有接入点信息的容器。", + "description": "保存所有接入点信息的容器。", + "type": "array", + "items": { + "description": "保存单个接入点信息的容器。", + "$ref": "#/components/schemas/AccessPoint" + } + } + } + }, + "LiveChannel": { + "title": "A short description of struct", + "description": "保存返回每个LiveChannel信息的容器。", + "type": "object", + "properties": { + "Name": { + "title": "description", + "description": "LiveChannel的名称。\n", + "type": "string", + "example": "channel-0" + }, + "Description": { + "title": "description", + "description": "LiveChannel的描述信息。\n", + "type": "string", + "example": "test" + }, + "Status": { + "title": "description", + "description": "LiveChannel的状态。\n有效值:\n- disabled:表示禁用LiveChannel。\n- enabled:表示启用LiveChannel。", + "type": "string", + "example": "enabled" + }, + "LastModified": { + "title": "description", + "description": "LiveChannel配置的最后修改时间。\n格式:ISO8601\n", + "type": "string", + "format": "iso8601", + "example": "ISO8601" + }, + "PublishUrls": { + "description": "保存LiveChannel对应的推流地址的容器。\n", + "$ref": "#/components/schemas/LiveChannelPublishUrls" + }, + "PlayUrls": { + "description": "保存LiveChannel对应的播放地址的容器。\n", + "$ref": "#/components/schemas/LiveChannelPlayUrls" + } + } + }, + "LiveChannelAudio": { + "title": "A short description of struct", + "description": "当Status为Live时,保存音频流信息的容器。\n> Video、Audio容器只有在Status为Live时才会返回,但Status为Live时不一定返回这两个容器。例如,客户端已经连接到LiveChannel,但尚未发送音视频数据,这种情况不会返回这两个容器。\n", + "type": "object", + "properties": { + "Bandwidth": { + "title": "description", + "description": "当前音频流的码率。\n> Bandwidth为音频流/视频流最近一段时间内的平均码率。LiveChannel刚切换到Live状态时,返回的Bandwidth值可能为0。\n单位:B/s\n", + "type": "integer", + "format": "int64", + "example": "0" + }, + "SampleRate": { + "title": "description", + "description": "当前音频流的采样率。\n", + "type": "integer", + "format": "int64", + "example": "44100" + }, + "Codec": { + "title": "description", + "description": "当前音频流的编码格式。\n", + "type": "string", + "example": "ADPCM" + } + } + }, + "LiveChannelConfiguration": { + "title": "A short description of struct", + "description": "保存LiveChannel配置的容器。", + "type": "object", + "properties": { + "Description": { + "title": "description", + "description": "LiveChannel的描述信息,最长128字节。\n", + "type": "string", + "example": "test" + }, + "Status": { + "title": "description", + "description": " 指定LiveChannel的状态。\n\n有效值:**enabled**、**disabled**\n默认值:**enabled**", + "type": "string", + "example": "enabled" + }, + "Target": { + "description": "保存转储配置的容器。\n", + "$ref": "#/components/schemas/LiveChannelTarget" + }, + "Snapshot": { + "description": "保存高频截图操作Snapshot选项的容器。\n", + "$ref": "#/components/schemas/LiveChannelSnapshot" + } + } + }, + "LiveChannelPlayUrls": { + "title": "A short description of struct", + "description": "保存播放地址的容器。\n", + "type": "object", + "properties": { + "Url": { + "title": "description", + "description": "播放地址。\n", + "type": "string", + "example": "http://test-bucket.oss-cn-hangzhou.aliyuncs.com/test-channel/playlist.m3u8" + } + } + }, + "LiveChannelPublishUrls": { + "title": "A short description of struct", + "description": "保存推流地址的容器。", + "type": "object", + "properties": { + "Url": { + "title": "description", + "description": "推流地址。\n\n> - 推流地址是未加签名的URL,如Bucket ACL非public-read-write,则需先进行签名才可访问。\n> - 播放地址是未加签名的URL,如Bucket ACL为private,则需先进行签名才可访问。", + "type": "string", + "example": "rtmp://test-bucket.oss-cn-hangzhou.aliyuncs.com/live/test-channel" + } + } + }, + "LiveChannelSnapshot": { + "title": "A short description of struct", + "description": "保存高频截图操作Snapshot 选项的容器。", + "type": "object", + "properties": { + "RoleName": { + "title": "description", + "description": "用于高频截图操作的角色名称,要求有DestBucket的写权限和向NotifyTopic发消息的权限。\n", + "type": "string", + "example": "role_for_snapshot" + }, + "DestBucket": { + "title": "description", + "description": "保存高频截图目标Bucket,要求与当前Bucket是同一个Owner。\n", + "type": "string", + "example": "snapshotdest" + }, + "NotifyTopic": { + "title": "description", + "description": "用于通知用户高频截图操作结果的MNS的Topic。\n", + "type": "string", + "example": "snapshotnotify" + }, + "Interval": { + "title": "description", + "description": "高频截图的间隔长度。如果该段间隔时间内没有关键帧(I 帧),那么该间隔时间不截图。\n单位:秒\n取值范围:[1, 100]", + "type": "integer", + "format": "int64", + "example": "5" + } + } + }, + "LiveChannelTarget": { + "title": "A short description of struct", + "description": "保存转储配置的容器。\n\n", + "type": "object", + "properties": { + "Type": { + "title": "description", + "description": "指定转储的类型。\n\n有效值:**HLS**\n\n> - 转储类型为HLS时,OSS会在生成每个ts文件后更新m3u8文件。m3u8文件中最多包含最近的FragCount个ts文件。\n> - 转储类型为HLS时,写入当前ts文件的音视频数据时长达到FragDuration指定的时长后,OSS会在收到下一个关键帧的时切换到下一个ts文件;如果max(2*FragDuration,\n 60s)后仍未收到下一个关键帧,OSS将强制切换文件,此时可能引起播放时卡顿。", + "type": "string", + "example": "HLS" + }, + "FragDuration": { + "title": "description", + "description": "当Type为HLS时,指定每个ts文件的时长。\n单位:秒\n\n取值范围:[1, 100]\n默认值:**5**\n> FragDuration和FragCount的默认值只有在两者都未指定时才会生效;指定了其中一个,则另一个的值也必须指定。", + "type": "integer", + "format": "int64", + "example": "5" + }, + "FragCount": { + "title": "description", + "description": "当Type为HLS时,指定m3u8文件中包含ts文件的个数。\n\n取值范围:[1, 100]\n默认值:**3**\n> FragDuration和FragCount的默认值只有在两者都未指定时才会生效;指定了其中一个,则另一个的值也必须指定。", + "type": "integer", + "format": "int64", + "example": "3" + }, + "PlaylistName": { + "title": "description", + "description": "当Type为HLS时,指定生成的m3u8文件的名称。必须以”.m3u8”结尾,长度范围为[6, 128]。\n\n默认值:**playlist.m3u8**\n取值范围:[6, 128]", + "type": "string", + "example": "playlist.m3u8" + } + } + }, + "LiveChannelVideo": { + "title": "A short description of struct", + "description": "当Status为Live时,保存视频流信息的容器。\n> **说明** Video、Audio容器只有在Status为Live时才会返回,但Status为Live时不一定返回这两个容器。例如,客户端已经连接到LiveChannel,但尚未发送音视频数据,这种情况不会返回这两个容器。\n", + "type": "object", + "properties": { + "Width": { + "title": "description", + "description": "当前视频流的画面宽度。\n单位:像素\n", + "type": "integer", + "format": "int64", + "example": "1280" + }, + "Height": { + "title": "description", + "description": "当前视频流的画面高度。\n单位:像素\n", + "type": "integer", + "format": "int64", + "example": "536" + }, + "FrameRate": { + "title": "description", + "description": "当前视频流的帧率。\n", + "type": "integer", + "format": "int64", + "example": "24" + }, + "Bandwidth": { + "title": "description", + "description": "当前视频流的码率。\n单位:B/s\n", + "type": "integer", + "format": "int64", + "example": "0" + }, + "Codec": { + "title": "description", + "description": "当前视频流的编码格式。\n", + "type": "string", + "example": "ADPCM" + } + } + }, + "LiveRecord": { + "title": "A short description of struct", + "description": "保存一次推流记录信息的容器。\n", + "type": "object", + "properties": { + "StartTime": { + "title": "description", + "description": "推流开始时间,使用ISO8601格式表示。\n", + "type": "string", + "example": "2016-07-30T01:53:21.000Z" + }, + "EndTime": { + "title": "description", + "description": "推流结束时间,使用ISO8601格式表示。\n", + "type": "string", + "example": "2016-07-30T01:53:31.000Z" + }, + "RemoteAddr": { + "title": "description", + "description": "推流客户端的IP地址。\n", + "type": "string", + "example": "10.101.194.148:57632" + } + } + }, + "LocationTransferType": { + "title": "The container that stores regions in which the destination bucket can be located with the TransferType information", + "description": "包含TransferType的Location信息容器。\n\n", + "type": "object", + "properties": { + "Location": { + "title": "The region in which the destination bucket can be located", + "description": "可复制到的目标Bucket所在的地域。", + "type": "string", + "example": "oss-cn-beijing" + }, + "TransferTypes": { + "title": "The container that stores the transmission type", + "description": "传输类型容器。", + "type": "object", + "properties": { + "Type": { + "title": "The link used to transfer data in Cross-region replication", + "description": "数据复制时使用的数据传输类型。\n取值:\n - internal(默认值):OSS默认传输链路。\n - oss_acc:传输加速链路。只有创建跨区域复制规则时才能使用传输加速链路。", + "type": "string", + "example": "oss_acc" + } + } + } + } + }, + "LoggingEnabled": { + "title": "A short description of struct", + "description": "访问日志信息的容器。\n", + "type": "object", + "properties": { + "TargetBucket": { + "title": "存储访问日志的存储空间", + "description": "指定存储访问日志的Bucket。\n", + "type": "string", + "required": true, + "example": "examplebucket" + }, + "TargetPrefix": { + "title": "保存的日志文件前缀", + "description": "指定保存的日志文件前缀,可以为空。\n", + "type": "string", + "example": "MyLog-" + } + } + }, + "MetaQuery": { + "title": "A short description of struct", + "description": "查询条件的容器。", + "type": "object", + "properties": { + "NextToken": { + "title": "翻页的Token", + "description": "翻页的Token。从NextToken开始按字典序返回Object信息列表。", + "type": "string", + "example": "MTIzNDU2Nzg6aW1tdGVzdDpleGFtcGxlYnVja2V0OmRhdGFzZXQwMDE6b3NzOi8vZXhhbXBsZWJ1Y2tldC9zYW1wbGVvYmplY3QxLmpw****" + }, + "MaxResults": { + "title": "返回对象的最大个数", + "description": "返回对象的最大个数,取值范围为0~100。\n不设置此参数或者设置为0时,则默认值为100。", + "type": "integer", + "format": "int64", + "example": "5" + }, + "Query": { + "title": "查询条件", + "description": "查询条件。包括如下选项:\n\n- Operation:操作符。取值范围为eq(等于)、gt(大于)、gte(大于等于)、lt(小于)、 lte(小于等于)、match(模糊查询)、prefix(前缀查询)、and(逻辑与)、or(逻辑或)和not(逻辑非)。\n\n- Field:字段名称。\n\n- Value:字段值。\n\n- SubQueries:子查询条件,包括的选项与简单查询条件相同。只有当Operations为逻辑运算符(and、or和not)时,才需要设置子查询条件。", + "type": "string", + "required": true, + "example": "{\"Field\": \"Size\",\"Value\": \"1048576\",\"Operation\": \"gt\"}" + }, + "Sort": { + "title": "对指定字段排序", + "description": "对指定字段排序。", + "type": "string", + "example": "Size" + }, + "Order": { + "description": "排序方式。", + "$ref": "#/components/schemas/MetaQueryOrder" + }, + "Aggregations": { + "title": "聚合操作信息", + "description": "聚合操作信息的容器。", + "type": "object", + "properties": { + "Aggregation": { + "title": "聚合操作信息", + "description": "单个聚合操作信息的容器。", + "type": "array", + "items": { + "description": "句号操作信息的容器。", + "$ref": "#/components/schemas/MetaQueryAggregation" + } + } + } + } + } + }, + "MetaQueryAggregation": { + "title": "聚合操作信息", + "description": "聚合操作信息", + "type": "object", + "properties": { + "Field": { + "title": "字段名称", + "description": "字段名称", + "type": "string", + "example": "Size" + }, + "Operation": { + "title": "聚合操作中的操作符", + "description": "聚合操作中的操作符。\n\n- min:最小值\n- max:最大值\n- average:平均数\n- sum:求和\n- count:计数\n- distinct:去重统计\n- group:分组计数", + "type": "string", + "example": "sum" + } + } + }, + "MetaQueryFile": { + "title": "A short description of struct", + "description": "A short description of struct", + "type": "object", + "properties": { + "Filename": { + "title": "对象的完整路径", + "description": "对象的完整路径", + "type": "string", + "example": "exampleobject.txt" + }, + "Size": { + "title": "对象大小", + "description": "对象大小", + "type": "integer", + "format": "int64", + "example": "120" + }, + "FileModifiedTime": { + "title": "最近一次修改时间", + "description": "最近一次修改时间", + "type": "string", + "example": "2021-06-29T15:04:05.000000000Z07:00" + }, + "OSSObjectType": { + "title": "对象的类型", + "description": "对象的类型", + "type": "string", + "enumValueTitles": { + "Multipart": "MultipartUpload上传的文件", + "Symlink": "PutSymlink创建的软链接", + "Appendable": "AppendObject上传的文件", + "Normal": "PutObject上传的文件" + }, + "example": "Normal" + }, + "OSSStorageClass": { + "title": "对象的存储类型", + "description": "对象的存储类型", + "type": "string", + "enumValueTitles": { + "Archive": "归档存储类型", + "ColdArchive": "冷归档存储类型文件", + "IA": "低频文件", + "Standard": "标准文件" + }, + "example": "Standard" + }, + "ObjectACL": { + "title": "对象的访问权限", + "description": "对象的访问权限", + "type": "string", + "enumValueTitles": { + "default": "遵循存储空间的访问权限", + "private": "私有", + "public-read": "公共读", + "public-read-write": "公共读写" + }, + "example": "default" + }, + "ETag": { + "title": "对象的ETAG", + "description": "对象的ETAG", + "type": "string", + "example": "\"fba9dede5f27731c9771645a3986****\"" + }, + "OSSCRC64": { + "title": "对象的CRC64校验值", + "description": "对象的CRC64校验值", + "type": "string", + "example": "4858A48BD1466884" + }, + "ServerSideEncryption": { + "title": "创建对象时的服务端加密密钥", + "description": "创建对象时的服务端加密密钥", + "type": "string", + "example": "AES256" + }, + "ServerSideEncryptionCustomerAlgorithm": { + "title": "创建对象时的服务端加密算法", + "description": "创建对象时的服务端加密算法", + "type": "string", + "example": "SM4" + }, + "OSSTaggingCount": { + "title": "对象的标签个数", + "description": "对象的标签个数", + "type": "integer", + "format": "int64", + "example": "16" + }, + "OSSTagging": { + "title": "对象的标签列表", + "description": "对象的标签列表", + "type": "object", + "properties": { + "Tagging": { + "title": "对象的标签", + "description": "对象的标签", + "type": "array", + "items": { + "description": "对象的标签", + "$ref": "#/components/schemas/MetaQueryTagging" + } + } + } + }, + "OSSUserMeta": { + "title": "对象的自定义元数据列表", + "description": "对象的自定义元数据列表", + "type": "object", + "properties": { + "UserMeta": { + "title": "对象的自定义元数据", + "description": "对象的自定义元数据", + "type": "array", + "items": { + "description": "用户自定义元数据", + "$ref": "#/components/schemas/MetaQueryUserMeta" + } + } + } + } + } + }, + "MetaQueryOrder": { + "title": "A short description of struct", + "description": "排序方式。取值范围如下:\n\n- asc:升序。\n\n- desc(默认值):降序。", + "type": "string", + "example": "asc", + "enum": [ + "asc", + "desc" + ] + }, + "MetaQueryTagging": { + "title": "A short description of struct", + "description": "对象所附标签", + "type": "object", + "properties": { + "Key": { + "title": "key", + "description": "对象标签键", + "type": "string", + "example": "abc" + }, + "Value": { + "title": "value", + "description": "对象标签值", + "type": "string", + "example": "test" + } + } + }, + "MetaQueryUserMeta": { + "title": "A short description of struct", + "description": "用户自定义元数据", + "type": "object", + "properties": { + "Key": { + "title": "key", + "description": "用户自定义元数据键", + "type": "string", + "example": "abc" + }, + "Value": { + "title": "value", + "description": "用户自定义元数据值", + "type": "string", + "example": "test" + } + } + }, + "ObjectACL": { + "description": "指定OSS创建Object时的访问权限。\n取值:\n\n- default(默认):Object遵循所在存储空间的访问权限。\n- private:Object是私有资源。只有Object的拥有者和授权用户有该Object的读写权限,其他用户没有权限操作该Object。\n- public-read:Object是公共读资源。只有Object的拥有者和授权用户有该Object的读写权限,其他用户只有该Object的读权限。请谨慎使用该权限。\n- public-read-write:Object是公共读写资源。所有用户都有该Object的读写权限。请谨慎使用该权限。\n\n关于访问权限的更多信息,请参见**[读写权限ACL](~~100676~~)**。", + "type": "string", + "example": "public-read", + "default": "default", + "enum": [ + "private", + "public-read", + "public-read-write", + "default" + ] + }, + "ObjectIdentifier": { + "title": "A short description of struct", + "description": "对象标识符。", + "type": "object", + "properties": { + "Key": { + "title": "key", + "description": "对象 Key。", + "type": "string", + "required": true, + "example": "object_key" + }, + "VersionId": { + "title": "version id", + "description": "版本ID。", + "type": "string", + "example": "version_20211101141621_d137" + } + } + }, + "ObjectList": { + "title": "A list of the objects.", + "description": "文件信息的容器", + "type": "array", + "items": { + "description": "返回的文件元信息。", + "$ref": "#/components/schemas/ObjectSummary" + }, + "enumValueTitles": {} + }, + "ObjectSummary": { + "title": "Object元信息", + "description": "返回的文件元信息。", + "type": "object", + "properties": { + "Key": { + "title": "Object名称", + "description": "Object的Key。", + "type": "string", + "example": "fun/test.jpg" + }, + "LastModified": { + "title": "Object最后被修改的时间", + "description": "Object最后被修改的时间。", + "type": "string", + "format": "iso8601", + "example": "2012-02-24T08:42:32.000Z" + }, + "ETag": { + "title": "在每个Object生成时创建,用于标识一个Object的内容", + "description": "ETag (Entity Tag) 在每个Object生成时创建,用于标识一个Object的内容。\n\n- 对于PutObject请求创建的Object,ETag值是其内容的MD5值。\n\n- 对于其他方式创建的Object,ETag值是基于一定计算规则生成的唯一值,但不是其内容的MD5值。\n\n- ETag值可以用于检查Object内容是否发生变化。不建议使用ETag值作为Object内容的MD5校验数据完整性的依据。", + "type": "string", + "example": "5B3C1A2E053D763E1B002CC607C5A0FE1****" + }, + "Type": { + "title": "Object类型", + "description": "Object的类型,包含以下三种:\n\n- 通过简单上传生成的Object类型为Normal。\n\n- 通过分片上传生成的Object类型为Multipart。\n\n- 通过追加上传生成的Object类型为Appendable,且仅支持在Appendable类型的Object后直接追加内容。", + "type": "string", + "example": "Normal" + }, + "Size": { + "title": "Object的大小,单位为字节", + "description": "返回Object大小,单位为字节。", + "type": "integer", + "format": "int64", + "example": "344606" + }, + "StorageClass": { + "title": "Object的存储类型", + "description": "Object的存储类型。", + "$ref": "#/components/schemas/StorageClass" + }, + "Owner": { + "title": "Bucket拥有者信息", + "description": "保存Bucket拥有者信息的容器。", + "$ref": "#/components/schemas/Owner" + }, + "ResoreInfo": { + "title": "Object的解冻状态", + "description": "Object的解冻状态", + "type": "string", + "example": "ongoing-request=\"true”" + } + } + }, + "ObjectVersion": { + "title": "The version of an object", + "description": "保存除删除标记以外的Object版本的容器。\n", + "type": "object", + "properties": { + "Key": { + "title": "The name of the object", + "description": "Object的名称。\n", + "type": "string", + "example": "example" + }, + "VersionId": { + "title": "The version ID of the object", + "description": "Object的版本ID。", + "type": "string", + "example": "CAEQMxiBgMDNoP2D0BYiIDE3MWUxNzgxZDQxNTRiODI5OGYwZGMwNGY3MzZjN****" + }, + "IsLatest": { + "title": "Indicates whether the version is the current version", + "description": "Object是否为当前版本。\n取值:\n\n- true:Object为当前版本。\n\n- false:Object为非当前版本。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true", + "default": "false" + }, + "LastModified": { + "title": "The last modified time of the object", + "description": "Object最后被修改的时间。", + "type": "string", + "format": "iso8601", + "example": "2019-04-09T07:27:28.000Z" + }, + "ETag": { + "title": "The entity tag", + "description": "每个Object生成时创建的ETag ,用于标识Object的内容。\n - 对于PutObject请求创建的Object,ETag值是其内容的MD5值。\n - 对于其他方式创建的Object,ETag值是基于一定计算规则生成的唯一值,但不是其内容的MD5值。\n\n> ETag值仅用于检查Object内容是否发生变化。不建议使用ETag值作为Object内容的MD5数据完整性校验的依据。\n", + "type": "string", + "example": "250F8A0AE989679A22926A875F0A2****" + }, + "Size": { + "title": "The size of the returned object", + "description": "Object的字节数。\n", + "type": "integer", + "format": "int64", + "example": "93731" + }, + "StorageClass": { + "description": "Object的存储类型。\n", + "example": "Standard", + "$ref": "#/components/schemas/StorageClass" + }, + "Owner": { + "title": "The information about the bucket owner", + "description": "保存Bucket拥有者信息的容器。\n", + "$ref": "#/components/schemas/Owner" + } + } + }, + "OutputSerialization": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "CSV": { + "description": "输出CSV的格式参数。", + "$ref": "#/components/schemas/CSVOutput" + }, + "JSON": { + "description": "输出JSON的格式参数。", + "$ref": "#/components/schemas/JSONOutput" + }, + "KeepAllColumns": { + "title": "description", + "description": "指定返回结果中包含CSV所有列的位置(可选)。
默认值:false\n
仅在select语句里出现的列会有值,不出现的列则为空,返回结果中每一行的数据按照CSV列的顺序从低到高排列。\n例如以下语句:
\n`select _5, _1 from ossobject.`\n
如果KeepAllColumns = true,假设一共有6列数据,则返回以下数据:\n
`Value of 1st column,,,,Value of 5th column,\\n`", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "OutputHeader": { + "title": "description", + "description": "在返回结果开头输出CSV头信息。\n
默认值:false", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "OutputRawData": { + "title": "description", + "description": "指定输出数据为纯数据。\n\n- 您在请求中指定OutputRawData值时,OSS服务端会按照请求中的要求返回数据。\n\n- 您在请求中不指定OutputRawData值时,OSS服务端会自动选择一种格式返回。\n\n- 当您显式地指定OutputRawData为True时,如果该SQL长时间内没有返回数据,则HTTP请求可能因没有数据返回而超时。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "EnablePayloadCrc": { + "title": "description", + "description": "在每个Frame中会有一个32位的CRC32校验值。客户端可以计算相应payload的CRC32值进行数据完整性校验。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + } + } + }, + "Owner": { + "title": "Container for the owner's display name and ID", + "description": "保存Bucket拥有者信息的容器。\n", + "type": "object", + "properties": { + "ID": { + "title": "The ID of the owner", + "description": "Bucket拥有者的用户ID。", + "type": "string", + "example": "ut_test_bucket" + }, + "DisplayName": { + "title": "The display name of the owner", + "description": "Bucket拥有者的名称 (目前和ID一致)。", + "type": "string", + "example": "ut_test_bucket" + } + } + }, + "Part": { + "title": "A short description of struct", + "description": "保存已上传Part信息的容器。\n", + "type": "object", + "properties": { + "ETag": { + "title": "description", + "description": "Part成功上传后,OSS返回的ETag值。", + "type": "string", + "example": "3349DC700140D7F86A0784842780****" + }, + "PartNumber": { + "title": "description", + "description": "Part数目。", + "type": "integer", + "format": "int64", + "example": "1" + }, + "Size": { + "title": "description", + "description": "已上传Part大小。", + "type": "integer", + "format": "int64", + "example": "6291456" + }, + "LastModified": { + "title": "description", + "description": "Part上传的时间。\n", + "type": "string", + "format": "iso8601", + "example": "2012-02-23T07:01:34.000Z" + } + } + }, + "RTC": { + "title": "数据复制时间控制功能的状态", + "description": "数据复制时间控制功能的状态", + "type": "object", + "properties": { + "Status": { + "title": "是否开启复制时间控制(RTC)功能", + "description": "是否开启复制时间控制(RTC)功能", + "type": "string", + "enumValueTitles": { + "disabled": "关闭RTC功能", + "enabled": "开启RTC功能" + }, + "example": "Enabled" + } + } + }, + "RefererConfiguration": { + "title": "A short description of struct", + "description": "保存Referer配置内容的容器。", + "type": "object", + "properties": { + "AllowEmptyReferer": { + "title": "是否允许Referer字段为空的请求访问", + "description": "指定是否允许Referer字段为空的请求访问OSS。取值如下:\n\n- true(默认值):允许Referer字段为空的请求访问OSS。\n- false:不允许Referer字段为空的请求访问OSS。", + "type": "boolean", + "required": true, + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true", + "default": "true" + }, + "AllowTruncateQueryString": { + "title": "匹配时是否截断请求参数", + "description": "是否截断QueryString。\n\n- true(默认值):截断QueryString。\n\n- false:不截断QueryString。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + }, + "RefererList": { + "title": "保存Referer访问白名单", + "description": "保存Referer访问白名单的容器。\n> **说明**PutBucketReferer为覆盖语义,即RefererList中的新指定的白名单列表将覆盖已配置的白名单列表。当您上传的RefererList为空时(即不包含Referer请求元素),此操作将清空RefererList中已配置的白名单列表。\n", + "type": "object", + "properties": { + "Referer": { + "title": "指定一条Referer访问白名单", + "description": "指定一条Referer访问白名单。\n", + "type": "array", + "items": { + "description": "指定一条Referer访问白名单。", + "type": "string", + "example": "http://www.aliyun.com" + } + } + }, + "required": true + }, + "TruncatePath": { + "title": "匹配时是否截断路径部分(即只匹配protocol://host/部分)", + "description": "匹配时是否截断路径部分(即只匹配protocol://host/部分)。取值:\n\n- true:截断URL中包括Path在内的后续所有部分。\n\n- false:不截断URL中包括Path在内的后续所有部分。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + } + } + }, + "RegionInfo": { + "title": "A short description of struct", + "description": "地域信息。", + "type": "object", + "properties": { + "Region": { + "title": "region", + "description": "地域ID。", + "type": "string", + "example": "oss-cn-hangzhou" + }, + "InternetEndpoint": { + "title": "internet endpoint", + "description": "地域对应的外网Endpoint。", + "type": "string", + "example": "oss-cn-hangzhou.aliyuncs.com" + }, + "InternalEndpoint": { + "title": "internal endpoint", + "description": "地域对应的内网Endpoint。", + "type": "string", + "example": "oss-cn-hangzhou-internal.aliyuncs.com" + }, + "AccelerateEndpoint": { + "title": "accelerate endpoint", + "description": "地域对应的传输加速Endpoint。取值固定为oss-accelerate.aliyuncs.com。", + "type": "string", + "example": "oss-accelerate.aliyuncs.com" + } + } + }, + "ReplicationConfiguration": { + "title": "A short description of struct", + "description": "数据复制配置信息。", + "type": "object", + "properties": { + "Rule": { + "description": "保存数据复制规则的容器。", + "$ref": "#/components/schemas/ReplicationRule" + } + } + }, + "ReplicationDestination": { + "title": "A short description of struct", + "description": "保存目标Bucket信息的容器。", + "type": "object", + "properties": { + "Bucket": { + "title": "The destination bucket to which the data is replicated", + "description": "指定数据要复制到的目标Bucket。\n", + "type": "string", + "example": "target-bucket" + }, + "Location": { + "title": "The region in which the destination bucket is located", + "description": "目标Bucket所处的地域。\n", + "type": "string", + "enumValueTitles": {}, + "example": "oss-cn-beijing" + }, + "TransferType": { + "title": "The link used to transfer data in CRR", + "description": "指定数据复制时使用的数据传输链路。\n取值:\n - internal(默认值):OSS默认传输链路。\n - oss_acc:传输加速链路。只有创建跨区域复制规则时才能使用传输加速链路。\n", + "type": "string", + "enumValueTitles": {}, + "example": "oss_acc" + } + } + }, + "ReplicationPrefixSet": { + "title": "The container that stores prefixes", + "description": "保存Prefix的容器,每个复制规则中,最多能指定10个Prefix。", + "type": "object", + "properties": { + "Prefix": { + "title": "Prefixs used to specify the object to replicate", + "description": "设置待复制Object的Prefix。只有匹配该Prefix的Object才被复制到目标Bucket。\n - Prefix最大长度为1023个字符。\n - 如果配置了Prefix,则新写入的数据和历史数据的同步都会遵循Prefix指定的规则。\n\n", + "type": "array", + "items": { + "description": "设置待复制Object的Prefix。只有匹配该Prefix的Object才被复制到目标Bucket。\n - Prefix最大长度为1023个字符。\n - 如果配置了Prefix,则新写入的数据和历史数据的同步都会遵循Prefix指定的规则。\n\n", + "type": "string", + "example": "video" + } + } + } + }, + "ReplicationProgressRule": { + "title": "A short description of struct", + "description": "数据复制进度信息", + "type": "object", + "properties": { + "ID": { + "title": "rule id", + "description": "rule id", + "type": "string", + "example": "rep01" + }, + "PrefixSet": { + "description": "保存Prefix 的容器,每个复制规则中,最多能指定10个Prefix。", + "$ref": "#/components/schemas/ReplicationPrefixSet" + }, + "Action": { + "title": "A short description of action", + "description": "表示被同步到目标Bucket的操作。\n\nAction允许以下操作类型,您可以指定一项或者多项。\n\nALL(默认操作):表示PUT、DELETE、ABORT操作均会被同步到目标Bucket。\n\nPUT:表示被同步到目标Bucket的写入操作,包括PutObject、PostObject、AppendObject、CopyObject、PutObjectACL、 InitiateMultipartUpload 、 UploadPart、UploadPartCopy和CompleteMultipartUpload。", + "type": "string", + "enumValueTitles": { + "ALL": "PUT/DELETE/ABORT操作都会同步", + "PUT": "仅同步写入类操作" + }, + "example": "PUT" + }, + "Destination": { + "description": "保存目标Bucket信息的容器。", + "$ref": "#/components/schemas/ReplicationDestination" + }, + "Status": { + "title": "A short description of action", + "description": "复制状态。", + "type": "string", + "example": "doing" + }, + "HistoricalObjectReplication": { + "title": "A short description of HistoricalObjectReplication", + "description": "是否复制历史数据。即开启数据复制前,是否将源Bucket中的数据复制到目标Bucket。\n\n取值:\n\nenabled(默认值):表示复制历史数据。\n\ndisabled:表示不复制历史数据,仅复制跨区域复制规则生效后新写入的数据。", + "type": "string", + "enumValueTitles": { + "disabled": "不复制历史数据", + "enabled": "复制历史数据" + }, + "example": "enabled" + }, + "Progress": { + "title": "A short description of Progress", + "description": "保存复制进度的容器,仅当数据处于同步状态(doing)时才返回此元素。", + "type": "object", + "properties": { + "HistoricalObject": { + "title": "A short description of HistoricalObject", + "description": "显示已复制历史数据的百分比。仅对开启了历史数据复制的Bucket有效。", + "type": "string", + "example": "0.86" + }, + "NewObject": { + "title": "A short description of NewObject", + "description": "显示数据复制到目标Bucket的时间点(GMT格式)。\n\n例如Thu, 24 Sep 2015 15:39:18 GMT,表示早于该时间点写入的数据都已复制到目标Bucket。", + "type": "string", + "example": "Thu, 24 Sep 2015 15:39:18 GMT" + } + } + } + } + }, + "ReplicationRule": { + "title": "A short description of struct", + "description": "数据复制规则。", + "type": "object", + "properties": { + "ID": { + "title": "rule id", + "description": "请求规则对应的ID。", + "type": "string", + "example": "test_replication_1" + }, + "PrefixSet": { + "description": "保存前缀(Prefix)的容器。每条数据复制规则中,最多可指定10条Prefix。\n", + "$ref": "#/components/schemas/ReplicationPrefixSet" + }, + "Action": { + "title": "A short description of action", + "description": "指定可以被复制到目标Bucket的操作。如果配置了Action,则新写入的数据和历史数据的同步都会遵循Action指定的复制操作。\nAction允许以下操作类型,您可以指定一项或多项。\n取值:\n - ALL(默认值):表示PUT、DELETE、ABORT操作均会被同步到目标Bucket。\n - PUT:表示被同步到目标Bucket的写入操作,包括PutObject、PostObject、AppendObject、CopyObject、PutObjectACL、InitiateMultipartUpload、UploadPart、UploadPartCopy、CompleteMultipartUpload。\n\n", + "type": "string", + "example": "PUT" + }, + "Destination": { + "description": "保存目标Bucket信息的容器。", + "$ref": "#/components/schemas/ReplicationDestination" + }, + "Status": { + "title": "A short description of action", + "description": "表示复制状态。\n取值:\n - starting:设置数据复制规则后,OSS会为Bucket准备复制任务,此时的复制状态为starting。\n - doing:当数据复制规则生效后,即数据处于同步状态时,此时的复制状态为doing。\n - closing:删除数据复制规则后,OSS会自动完成清理工作,此时的复制状态为closing。\n", + "type": "string", + "example": "starting" + }, + "HistoricalObjectReplication": { + "title": "A short description of HistoricalObjectReplication", + "description": "指定是否复制历史数据。即开启数据复制前,是否将源Bucket中的数据复制到目标Bucket。\n取值:\n - enabled(默认值):表示复制历史数据。\n - disabled:表示不复制历史数据。即仅复制创建数据复制规则后新写入的数据。\n\n", + "type": "string", + "example": "enabled" + }, + "SyncRole": { + "title": "A short description of SyncRole", + "description": "授权OSS使用哪个角色来进行数据复制。如果指定使用SSE-KMS加密目标对象,则必须指定该元素。", + "type": "string", + "example": "aliyunramrole" + }, + "SourceSelectionCriteria": { + "description": "用于标识要复制的源对象的其他筛选条件的容器。当前OSS仅支持针对SSE-KMS加密的源对象指定筛选条件。", + "$ref": "#/components/schemas/ReplicationSourceSelectionCriteria" + }, + "EncryptionConfiguration": { + "title": "A short description of EncryptionConfiguration", + "description": "目标对象加密配置。如果指定Status为Enabled,则必须指定该元素。", + "type": "object", + "properties": { + "ReplicaKmsKeyID": { + "title": "kms id", + "description": "指定SSE-KMS密钥ID。如果指定Status为Enabled,则必须指定该元素。", + "type": "string", + "example": "c4d49f85-ee30-426b-a5ed-95e9139d****" + } + } + } + } + }, + "ReplicationRuleProgress": { + "title": "A short description of struct", + "description": "数据复制规则进度信息。", + "type": "object", + "properties": { + "ID": { + "title": "id", + "description": "复制规则对应的ID。", + "type": "string", + "example": "test_replication_rule_1" + }, + "PrefixSet": { + "description": "保存Prefix 的容器,每个复制规则中,最多能指定10个Prefix。", + "$ref": "#/components/schemas/ReplicationPrefixSet" + }, + "Action": { + "title": "action", + "description": "表示被同步到目标Bucket的操作。\nAction允许以下操作类型,您可以指定一项或者多项。\n\n- ALL(默认操作):表示PUT、DELETE、ABORT操作均会被同步到目标Bucket。\n\n- PUT:表示被同步到目标Bucket的写入操作,包括PutObject、PostObject、AppendObject、CopyObject、PutObjectACL、InitiateMultipartUpload 、 UploadPart、UploadPartCopy和CompleteMultipartUpload。", + "type": "string", + "example": "ALL" + } + } + }, + "ReplicationRules": { + "title": "A short description of struct", + "description": "保存需要删除的数据复制规则的容器。", + "type": "object", + "properties": { + "ID": { + "title": "the container of id", + "description": "需要删除的复制规则对应的ID。规则ID可从GetBucketReplication中获取。", + "type": "array", + "items": { + "description": "需要删除的复制规则对应的ID。规则ID可从GetBucketReplication中获取。", + "type": "string", + "example": "test_replication_1" + } + } + } + }, + "ReplicationSourceSelectionCriteria": { + "title": "A short description of struct", + "description": "用于标识要复制的源对象的其他筛选条件的容器。当前OSS仅支持针对SSE-KMS加密的源对象指定筛选条件。", + "type": "object", + "properties": { + "SseKmsEncryptedObjects": { + "title": "A short description of SseKmsEncryptedObjects", + "description": "用于筛选使用SSE-KMS加密对象的容器。如果在数据复制规则中指定了SourceSelectionCriteria,则必须指定该元素。", + "type": "object", + "properties": { + "Status": { + "title": "A short description of Status", + "description": "指定OSS是否复制通过SSE-KMS加密创建的对象。取值范围如下:\n - Enabled:表示复制通过SSE-KMS加密创建的对象。\n - Disabled:表示不复制通过SSE-KMS加密创建的对象。", + "type": "string", + "example": "Enabled" + } + } + } + } + }, + "RequestPaymentConfiguration": { + "title": "A short description of struct", + "description": "请求付费配置的容器。\n", + "type": "object", + "properties": { + "Payer": { + "title": "description", + "description": "指定Bucket付费类型。\n取值:\n\n- BucketOwner:由Bucket拥有者付费。\n\n- Requester:由请求者付费。", + "type": "string", + "example": "Requester" + } + } + }, + "ResourceGroupId": { + "title": "Bucket所属的资源组ID", + "description": "指定资源组ID。\n\n- 如果在请求中携带该请求头并指定资源组ID,则OSS会返回属于该资源组的所有Bucket。当指定的资源组ID为rg-default-id时,OSS会返回属于默认资源组的所有Bucket。\n- 如果在请求中携带了该请求头但未指定资源组ID,则OSS会返回属于默认资源组的所有Bucket。\n- 如果在请求中未携带该请求头,则OSS会返回请求者拥有的所有Bucket。您可以通过资源管理的控制台或ListResourceGroups接口获取资源组ID。\n\n您可以通过资源管理的控制台或ListResourceGroups接口获取资源组ID。具体操作,请分别参见[查看资源组基本信息](~~151181~~)和[ListResourceGroups](~~158855~~)。", + "type": "string", + "example": "rg-aekz****" + }, + "RestoreRequest": { + "title": "A short description of struct", + "description": "解冻请求信息。", + "type": "object", + "properties": { + "Days": { + "title": "description", + "description": "解冻的天数。取值范围为1~7天。\n", + "type": "integer", + "format": "int64", + "example": "2" + }, + "JobParameters": { + "title": "description", + "description": "解冻优先级的容器。只有解冻冷归档类型的Object时才生效。\n如果不传入JobParameters节点,则解冻优先级默认为Standard。\n", + "type": "object", + "properties": { + "Tier": { + "title": "description", + "description": "解冻优先级。取值范围如下:\n - 高优先级(Expedited):表示1小时内完成解冻。\n - 标准(Standard):表示2~5小时内完成解冻。\n - 批量(Bulk):表示5~12小时内完成解冻。\n", + "type": "string", + "example": "Standard" + } + } + } + } + }, + "RoutingRule": { + "title": "A short description of struct", + "description": "指定跳转规则或者镜像回源规则,最多指定20个RoutingRule。\n", + "type": "object", + "properties": { + "RuleNumber": { + "title": "description", + "description": "匹配和执行RoutingRule的序号,OSS将按照此序号依次匹配规则。如果匹配成功,则执行此规则,后续的规则不再执行。\n\n>如果指定了父节点RoutingRule,则必须指定此项。", + "type": "integer", + "format": "int64", + "example": "1" + }, + "Condition": { + "title": "description", + "description": "匹配的条件。\n如果指定的项都满足,则执行此规则。只有满足此容器下的各个节点的所有条件才算匹配。\n>如果指定了父节点RoutingRule,则必须指定此项。", + "$ref": "#/components/schemas/RoutingRuleCondition" + }, + "Redirect": { + "title": "description", + "description": "指定匹配此规则后执行的动作。\n>如果指定了父节点RoutingRule,则必须指定此项。", + "$ref": "#/components/schemas/RoutingRuleRedirect" + } + } + }, + "RoutingRuleCondition": { + "title": "A short description of struct", + "description": "匹配的条件。\n如果指定的项都满足,则执行此规则。只有满足此容器下的各个节点的所有条件才算匹配。\n>如果指定了父节点RoutingRule,则必须指定此项。", + "type": "object", + "properties": { + "KeyPrefixEquals": { + "title": "A short description of struct", + "description": "只有匹配此前缀的Object才能匹配此规则。\n", + "type": "string", + "example": "abc" + }, + "HttpErrorCodeReturnedEquals": { + "title": "A short description of struct", + "description": "访问指定Object时,返回此status才能匹配此规则。当跳转规则是镜像回源类型时,此字段必须为404。\n", + "type": "integer", + "format": "int64", + "example": "404" + } + } + }, + "RoutingRuleRedirect": { + "title": "A short description of struct", + "description": "指定匹配此规则后执行的动作。\n>如果指定了父节点RoutingRule,则必须指定此项。", + "type": "object", + "properties": { + "RedirectType": { + "title": "description", + "description": "指定跳转的类型。取值范围如下:\n - **Mirror**:镜像回源。\n - **External**:外部跳转,即OSS会返回一个3xx请求,指定跳转到另外一个地址。\n - **AliCDN**:阿里云CDN跳转,主要用于阿里云的CDN。与External不同的是,OSS会额外添加一个Header。阿里云CDN识别到此Header后会主动跳转到指定的地址,返回给用户获取到的数据,而不是将3xx跳转请求返回给用户。\n\n>如果指定了父节点Redirect,则必须指定此项。", + "type": "string", + "example": "Mirror" + }, + "PassQueryString": { + "title": "description", + "description": "执行跳转或者镜像回源规则时,是否携带请求参数。\n用户请求OSS时携带了请求参数`?a=b&c=d`,并且设置**PassQueryString**为true,如果规则为302跳转,则跳转的Location头中会添加此请求参数。例如`Location:example.com?a=b&c=d`,跳转类型为镜像回源,则在发起的回源请求中也会携带此请求参数。\n取值:true、false(默认)\n", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + }, + "MirrorURL": { + "title": "description", + "description": "镜像回源的源站地址。只有设置RedirectType为Mirror时才生效。\n源站地址必须以**http://**或者**https://**开头,并且以正斜线(/)结尾,OSS会在此地址后带上Object名称组成回源URL。\n例如要访问的Object名称为myobject,如果指定此项为`http://example.com/`,则回源URL为`http://example.com/myobject`,如果指定此项为`http://example.com/dir1/`,则回源URL为`http://example.com/dir1/myobject`。\n>如果RedirectType指定为Mirror,则必须指定此项。", + "type": "string", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "http://example.com" + }, + "TransparentMirrorResponseCodes": { + "title": "description", + "description": "指定当源站返回哪些状态码时需要透传该状态码以及body到客户端,取值为4xx、5xx等HTTP状态码,多个HTTP状态码之间用英文逗号(,)分隔,例如`400,404`。只有设置RedirectType为Mirror时才生效。\n当OSS向源站请求内容时,如果源站返回了此参数中的某个状态码,则OSS将透传源站返回的该状态码以及body到客户端。\n> 如果在此参数中设置了404状态码,则设置的ErrorDocument会失效。\n", + "type": "string", + "example": "400,404" + }, + "MirrorPassQueryString": { + "title": "description", + "description": "与PassQueryString作用相同,优先级高于PassQueryString。只有设置RedirectType为Mirror时才生效。\n默认值:false\n", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "MirrorFollowRedirect": { + "title": "description", + "description": "如果镜像回源获取的结果为3xx,是否继续跳转到指定的Location获取数据。 只有设置RedirectType为Mirror时才生效。\n例如发起镜像回源请求时,源站返回了302,并且指定了Location。\n - 如果设置此项为true,则OSS会继续请求Location对应的地址。\n最多能跳转10次,如果跳转超过10次,则返回镜像回源失败。\n - 如果设置此项为false,则OSS会返回302,并透传Location。\n\n默认值:true\n", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + }, + "MirrorCheckMd5": { + "title": "description", + "description": "是否检查回源body的MD5。 只有设置RedirectType为Mirror时才生效。\n当设置**MirrorCheckMd5**为true,并且源站返回的response中含有Content-Md5头时,OSS检查拉取的数据MD5是否与此Header匹配,如果不匹配,则不保存在OSS上。\n默认值:false", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "MirrorHeaders": { + "title": "description", + "description": "指定镜像回源时携带的Header。只有设置RedirectType为Mirror时才生效。\n", + "type": "object", + "properties": { + "PassAll": { + "title": "description", + "description": " 是否透传除以下Header之外的其他Header到源站。只有设置RedirectType为Mirror时才生效。\n - content-length、authorization2、authorization、range、date等Header\n - 以oss-/x-oss-/x-drs-开头的Header\n\n默认值:false\n", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "Pass": { + "title": "description", + "description": "透传指定的Header到源站。只有设置RedirectType为Mirror时才生效。\n每个Header长度最多为1024个字节,字符集为0~9、A~Z、a~z以及短划线(-)。\n此字段最多可指定10个。\n", + "type": "array", + "items": { + "description": "透传指定的Header到源站。只有设置RedirectType为Mirror时才生效。\n每个Header长度最多为1024个字节,字符集为0~9、A~Z、a~z以及短划线(-)。\n此字段最多可指定10个。\n", + "type": "string", + "example": "myheader-key1" + } + }, + "Remove": { + "title": "description", + "description": "禁止透传指定的Header到源站。只有设置RedirectType为Mirror时才生效。\n每个Header长度最多为1024个字节,字符集与Pass相同。\n此字段最多可指定10个,通常与PassAll一起使用。\n", + "type": "array", + "items": { + "description": "禁止透传指定的Header到源站。只有设置RedirectType为Mirror时才生效。\n每个Header长度最多为1024个字节,字符集与Pass相同。\n此字段最多可指定10个,通常与PassAll一起使用。\n", + "type": "string", + "example": "myheader-key3" + } + }, + "Set": { + "title": "description", + "description": "设置一个Header传到源站,不管请求中是否携带这些指定的Header,回源时都会设置这些Header。只有设置RedirectType为Mirror时才生效。\n此容器最多可指定10组。\n", + "type": "array", + "items": { + "description": "设置一个Header传到源站,不管请求中是否携带这些指定的Header,回源时都会设置这些Header。只有设置RedirectType为Mirror时才生效。\n此容器最多可指定10组。\n", + "type": "object", + "properties": { + "Key": { + "title": "description", + "description": "设置Header的key,最多1024个字节,字符集与Pass相同。只有设置RedirectType为Mirror时才生效。\n>若指定了父节点Set,则必须指定此项。", + "type": "string", + "example": "myheader-key5" + }, + "Value": { + "title": "description", + "description": "设置Header的value,最多1024个字节,不能出现`\\r\\n`。只有设置RedirectType为Mirror时才生效。\n>若指定了父节点Set,则必须指定此项。", + "type": "string", + "example": "myheader-value5" + } + } + } + } + } + }, + "Protocol": { + "title": "description", + "description": "跳转时的协议。只有设置RedirectType为External或者AliCDN时才生效。\n如果要访问的文件为test,设置跳转到`example.com`,并且设置Protocol为https,则Location头为`https://example.com/test`。\n取值:**http**、**https**。\n", + "type": "string", + "example": "http" + }, + "HostName": { + "title": "description", + "description": "跳转时的域名,域名需符合域名规范。\n如果要访问的文件为test,设置Protocol为https,并且设置Hostname为`example.com`,则Location头为`https://example.com/test`。\n", + "type": "string", + "example": "example.com" + }, + "ReplaceKeyPrefixWith": { + "title": "description", + "description": "Redirect时Object名称的前缀将替换成该值。如果前缀为空,则将这个字符串插入Object名称的前面。\n> 仅允许存在ReplaceKeyWith或ReplaceKeyPrefixWith节点。\n假设要访问的Object为abc/test.txt,如果设置KeyPrefixEquals为abc/,ReplaceKeyPrefixWith为def/,则Location头为`http://example.com/def/test.txt`。\n", + "type": "string", + "example": "def/" + }, + "EnableReplacePrefix": { + "title": "description", + "description": "如果设置此字段为true,则Object的前缀将被替换为ReplaceKeyPrefixWith指定的值。如果未指定此字段或为空,则表示截断Object前缀。\n> 当ReplaceKeyWith字段不为空时,不能设置此字段为true。\n\n默认值:false\n", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + }, + "ReplaceKeyWith": { + "title": "description", + "description": "Redirect时Object名称将替换成ReplaceKeyWith指定的值,ReplaceKeyWith支持设置变量。目前支持的变量为${key},表示该请求中的Object名称。\n假设要访问的Object为test,如果设置ReplaceKeyWith为`prefix/${key}.suffix`,则Location头为`http://example.com/prefix/test.suffix`。\n", + "type": "string", + "example": "prefix/${key}.suffix" + }, + "HttpRedirectCode": { + "title": "description", + "description": "跳转时返回的状态码。只有设置RedirectType为External或者AliCDN时才生效。\n取值:301(默认)、302、307。\n", + "type": "integer", + "format": "int64", + "example": "301" + } + } + }, + "RtcConfiguration": { + "title": "数据复制时间控制配置容器。", + "description": "数据复制时间控制配置容器。", + "type": "object", + "properties": { + "RTC": { + "description": "保存RTC状态规则的容器。", + "$ref": "#/components/schemas/RTC" + }, + "ID": { + "title": "需要设置RTC状态的复制规则ID。", + "description": "需要设置RTC状态的复制规则ID。", + "type": "string", + "example": "test_replication_rule_1" + } + } + }, + "SSEKMS": { + "title": "The container that stores the CMK used in the SSE-KMS encryption method", + "description": "保存SSE-KMS加密密钥的容器。\n\n", + "type": "object", + "properties": { + "KeyId": { + "title": "The CMK used in the SSE-KMS encryption method", + "description": "KMS密钥ID。", + "type": "string", + "example": "9468da86-3509-4f8d-a61e-6eab1eac****" + } + } + }, + "SSEOSS": { + "title": "The container that stores the information about the SSE-OSS encryption method", + "description": "使用OSS完全托管密钥进行加解密。", + "type": "object", + "properties": {}, + "example": "SSE-OSS" + }, + "SelectMetaRequest": { + "title": "A short description of struct", + "description": "保存SelectMetaRequest信息的容器。", + "type": "object", + "properties": { + "InputSerialization": { + "description": "输入序列化参数(可选)。", + "$ref": "#/components/schemas/InputSerialization" + }, + "OverwriteIfExists": { + "title": "description", + "description": "重新计算SelectMeta,覆盖已有数据。\n
默认值:false(即如果Select Meta已存在则直接返回)。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "false" + } + } + }, + "SelectMetaStatus": { + "title": "A short description of struct", + "description": "保存CreateSelectObjectMeta信息的容器。", + "type": "object", + "properties": { + "Offset": { + "title": "description", + "description": "8位整数,扫描结束时的文件偏移。", + "type": "integer", + "format": "int64", + "example": "0x0000000000000065" + }, + "TotalScannedBytes": { + "title": "description", + "description": "8位整数,最终扫描过的数据大小。", + "type": "integer", + "format": "int64", + "example": "0x0000000000000065" + }, + "Status": { + "title": "description", + "description": "4位整数,最终的status。", + "type": "integer", + "format": "int64", + "example": "0x000000c8" + }, + "SplitsCount": { + "title": "description", + "description": "4位整数,总split个数。", + "type": "integer", + "format": "int64", + "example": "0x00000001" + }, + "RowsCount": { + "title": "description", + "description": "8位整数,总行数。", + "type": "integer", + "format": "int64", + "example": "0x0000000000000003" + }, + "ColsCount": { + "title": "description", + "description": "4位整数,总列数。", + "type": "integer", + "format": "int64", + "example": "0x00000004" + }, + "ErrorMessage": { + "title": "description", + "description": "详细的错误信息。如果无错误,则error_message为空。", + "type": "string", + "example": "The body size in select request exceeds the max allowed size." + } + } + }, + "SelectProcess": { + "description": "SelectObject可选的x-oss-process参数", + "type": "string", + "example": "csv/select" + }, + "SelectRequest": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "Expression": { + "title": "description", + "description": "以Base64 编码的SQL语句。", + "type": "string", + "example": "c2VsZWN0IGNvdW50KCopIGZyb20gb3Nzb2JqZWN0IHdoZXJlIF80ID4gNDU=" + }, + "InputSerialization": { + "description": "输入序列化参数。", + "$ref": "#/components/schemas/InputSerialization" + }, + "OutputSerialization": { + "description": "输出序列化参数。", + "$ref": "#/components/schemas/OutputSerialization" + }, + "Options": { + "description": "其他可选参数。", + "$ref": "#/components/schemas/SelectRequestOptions" + } + } + }, + "SelectRequestOptions": { + "title": "A short description of struct", + "description": "保存Select请求的容器。", + "type": "object", + "properties": { + "SkipPartialDataRecord": { + "title": "description", + "description": "忽略缺失数据的行。\n\n- 当该参数为false时,OSS会忽略缺失某些列(该列值当做null)而不报错。\n\n- 当该参数为true时,该行数据因为不完整而被整体跳过。当跳过的行数超过指定的最大跳过行数时OSS会报错并停止处理。", + "type": "boolean", + "enumValueTitles": { + "false": "false", + "true": "true" + }, + "example": "false" + }, + "MaxSkippedRecordsAllowed": { + "title": "description", + "description": "指定最大能容忍的跳过的行数。当某一行数据因为不匹配SQL中期望的类型、或者某一列或者多列数据缺失且SkipPartialDataRecord为True时,该行数据会被跳过。如果跳过的行数超过该参数的值,OSS会停止处理并报错。\n
默认值:0\n\n> 如果某一行是非法CSV行,例如在一列中间连续含有奇数个quote字符,则OSS会马上停止处理并报错,因为该错误很可能会影响对整个CSV文件的解析。即该参数用来调整对非整齐数据的容忍度,但不应用于非法的CSV文件。", + "type": "integer", + "format": "int64", + "example": "0" + } + } + }, + "ServerSideEncryptionRule": { + "title": "A short description of struct", + "description": "服务器端加密规则的容器。\n", + "type": "object", + "properties": { + "ApplyServerSideEncryptionByDefault": { + "description": "服务器端默认加密方式的容器。\n", + "$ref": "#/components/schemas/ApplyServerSideEncryptionByDefault" + } + } + }, + "StorageClass": { + "title": "The storage class of a bucket.", + "description": "Bucket的存储类型。 取值范围如下:\n\n- Standard(默认):标准存储\n- IA:低频访问\n- Archive:归档存储\n- ColdArchive:冷归档存储\n- DeepColdArchive:深度冷归档存储", + "type": "string", + "enumValueTitles": { + "Archive": "Archive", + "ColdArchive": "ColdArchive", + "IA": "IA", + "Standard": "Standard" + }, + "example": "Standard", + "default": "Standard", + "enum": [ + "Standard", + "IA", + "Archive", + "ColdArchive", + "DeepColdArchive" + ] + }, + "Style": { + "title": "A short description of struct", + "description": "保存Content信息列表的容器。", + "type": "object", + "properties": { + "Content": { + "title": "样式内容", + "description": "图片样式内容,图片样式可以包含一个或多个图片处理操作。\n\n- 包含单个图片处理操作的图片样式,例如image/resize,p_50,表示将原图缩放50%。\n\n- 包含多个图片处理操作的图片样式,例如image/resize,p_63/quality,q_90,表示先将图片缩放到原图的63%,再设置图片相对质量为90%。", + "type": "string", + "example": "image/resize,p_50" + } + } + }, + "StyleInfo": { + "title": "A short description of struct", + "description": "包含存储空间图片处理样式信息的结构体", + "type": "object", + "properties": { + "Name": { + "title": "样式名称", + "description": "样式名称", + "type": "string", + "example": "imagestyle" + }, + "Content": { + "title": "图片", + "description": "样式内容", + "type": "string", + "example": "image/resize,p_50" + }, + "CreateTime": { + "title": "样式创建时间", + "description": "样式创建时间", + "type": "string", + "example": "Wed, 20 May 2020 12:07:15 GMT" + }, + "LastModifyTime": { + "title": "样式创建时间", + "description": "样式创建时间", + "type": "string", + "example": "Wed, 21 May 2020 12:07:15 GMT" + } + } + }, + "Tag": { + "title": "标签键值对", + "description": "设置Bucket Tag的容器。\n", + "type": "object", + "properties": { + "Key": { + "title": "key", + "description": "指定Bucket Tag的Key。\n\n> - 最大长度为64字节。\n> - 不能以`http ://`、`https://`、`Aliyun`为前缀。\n> - 必须为UTF-8编码。\n> - 不能为空。", + "type": "string", + "required": true, + "example": "testb" + }, + "Value": { + "title": "value", + "description": "指定Bucket Tag的Value。\n > - 最大长度为128字节。\n > - 必须为UTF-8编码。\n > - 可以为空。", + "type": "string", + "example": "testv2" + } + } + }, + "TagSet": { + "title": "A short description of struct", + "description": "标签集合。", + "type": "object", + "properties": { + "Tag": { + "title": "A short description of struct", + "description": "标签集合。", + "type": "array", + "items": { + "description": "标签集合。", + "$ref": "#/components/schemas/Tag" + } + } + } + }, + "Tagging": { + "title": "A short description of struct", + "description": "设置Bucket TagSet的容器。\n", + "type": "object", + "properties": { + "TagSet": { + "title": "the container of tags", + "description": "包含一系列Bucket Tag的容器。\n", + "required": false, + "$ref": "#/components/schemas/TagSet" + } + } + }, + "TransferAccelerationConfiguration": { + "title": "A short description of struct", + "description": "传输加速配置的容器。", + "type": "object", + "properties": { + "Enabled": { + "title": "是否开启传输加速", + "description": "目标Bucket是否开启传输加速。取值如下:\n - **true**:开启传输加速。\n - **false**:关闭传输加速。\n\n> 传输加速开启及关闭操作在30分钟内生效。", + "type": "boolean", + "enumValueTitles": { + "true": "true", + "false": "false" + }, + "example": "true" + } + } + }, + "Upload": { + "title": "A short description of struct", + "description": "保存Multipart Upload事件信息的容器。", + "type": "object", + "properties": { + "Key": { + "title": "description", + "description": "初始化Multipart Upload事件的Object名称。\n\n\n\n> OSS的返回结果按照Object名称字典序升序排列,对于同一个Object,则按照UploadId的字典序升序排列。", + "type": "string", + "example": "multipart.data" + }, + "UploadId": { + "title": "description", + "description": "Multipart Upload事件的ID。\n", + "type": "string", + "example": "0004B999EF5A239BB9138C6227D6****" + }, + "Initiated": { + "title": "description", + "description": "Multipart Upload事件初始化的时间。\n", + "type": "string", + "format": "iso8601", + "example": "2012-02-23T04:18:23.000Z" + } + } + }, + "UserAntiDDOSInfo": { + "title": "A short description of struct", + "description": "高防实例信息。", + "type": "object", + "properties": { + "InstanceId": { + "title": "拥有者的UID", + "description": "高防实例ID。", + "type": "string", + "example": "cbcac8d2-4f75-4d6d-9f2e-c3447f73****" + }, + "Owner": { + "title": "拥有者的UID", + "description": "高防实例拥有者的UID。", + "type": "string", + "example": "114893010724****" + }, + "Ctime": { + "title": "高防实例创建时间", + "description": "高防实例创建时间,格式为时间戳。", + "type": "integer", + "format": "int64", + "example": "1626769503" + }, + "Mtime": { + "title": "高防实例更新时间", + "description": "高防实例更新时间,格式为时间戳。", + "type": "integer", + "format": "int64", + "example": "1626769840" + }, + "ActiveTime": { + "title": "高防实例激活时间", + "description": "高防实例激活时间,格式为时间戳。", + "type": "integer", + "format": "int64", + "example": "1626769845" + }, + "Status": { + "title": "高防实的状态", + "description": "高防实例所处状态。\n\n- Init:初始化防护状态。\n\n- Defending:防护中状态。\n\n- HaltDefending:解除防护状态。", + "type": "string", + "example": "Defending" + } + } + }, + "VersioningConfiguration": { + "title": "Describes the versioning state of a OSS bucket", + "description": "保存版本控制状态的容器。", + "type": "object", + "properties": { + "Status": { + "description": "版本控制状态。取值如下:\n\n- Enabled:开启版本控制状态。\n\n- Suspended:暂停版本控制状态。", + "enumValueTitles": { + "Enabled": "Enabled", + "Suspended": "Suspended" + }, + "example": "Enabled", + "$ref": "#/components/schemas/BucketVersioningStatus" + } + } + }, + "VpcId": { + "title": "VPC ID", + "description": "VPC ID", + "type": "string", + "example": "vpc-t4nlw426y44rd3iq4****" + }, + "WebsiteConfiguration": { + "title": "A short description of struct", + "description": "根节点。", + "type": "object", + "properties": { + "IndexDocument": { + "description": "默认主页的容器。\n\n>至少指定IndexDocument、ErrorDocument、RoutingRules三个容器中的一个。", + "$ref": "#/components/schemas/IndexDocument" + }, + "ErrorDocument": { + "description": "404页面的容器。\n\n>至少指定IndexDocument、ErrorDocument、RoutingRules三个容器中的一个。", + "$ref": "#/components/schemas/ErrorDocument" + }, + "RoutingRules": { + "title": "description", + "description": "RoutingRule的容器。\n\n>至少指定IndexDocument、ErrorDocument、RoutingRules三个容器中的一个。", + "type": "object", + "properties": { + "RoutingRule": { + "title": "description", + "description": "指定跳转规则或者镜像回源规则,最多指定20个RoutingRule。\n", + "type": "array", + "items": { + "description": "指定跳转规则或者镜像回源规则,最多指定20个RoutingRule。\n", + "$ref": "#/components/schemas/RoutingRule" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/media/src/mocks/endpoints.ts b/media/src/mocks/endpoints.ts new file mode 100644 index 0000000..9a6ae5b --- /dev/null +++ b/media/src/mocks/endpoints.ts @@ -0,0 +1,264 @@ +export const endpointsMocks = [ + { + "regionId": "us-west-1", + "regionName": "美国(硅谷)", + "areaId": "europeAmerica", + "areaName": "欧洲与美洲", + "public": "ecs.us-west-1.aliyuncs.com", + "vpc": "ecs-vpc.us-west-1.aliyuncs.com" + }, + { + "regionId": "us-east-1", + "regionName": "美国(弗吉尼亚)", + "areaId": "europeAmerica", + "areaName": "欧洲与美洲", + "public": "ecs.us-east-1.aliyuncs.com", + "vpc": "ecs-vpc.us-east-1.aliyuncs.com" + }, + { + "regionId": "me-east-1", + "regionName": "阿联酋(迪拜)", + "areaId": "middleEast", + "areaName": "中东与印度", + "public": "ecs.me-east-1.aliyuncs.com", + "vpc": "ecs-vpc.me-east-1.aliyuncs.com" + }, + { + "regionId": "me-central-1", + "regionName": "沙特(利雅得)", + "areaId": "middleEast", + "areaName": "中东与印度", + "vpc": "ecs-vpc.me-central-1.aliyuncs.com" + }, + { + "regionId": "eu-west-1", + "regionName": "英国(伦敦)", + "areaId": "europeAmerica", + "areaName": "欧洲与美洲", + "public": "ecs.eu-west-1.aliyuncs.com", + "vpc": "ecs-vpc.eu-west-1.aliyuncs.com" + }, + { + "regionId": "eu-central-1", + "regionName": "德国(法兰克福)", + "areaId": "europeAmerica", + "areaName": "欧洲与美洲", + "public": "ecs.eu-central-1.aliyuncs.com", + "vpc": "ecs-vpc.eu-central-1.aliyuncs.com" + }, + { + "regionId": "cn-zhangjiakou", + "regionName": "华北3(张家口)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-zhangjiakou.aliyuncs.com", + "vpc": "ecs-vpc.cn-zhangjiakou.aliyuncs.com" + }, + { + "regionId": "cn-wulanchabu", + "regionName": "华北6(乌兰察布)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-wulanchabu.aliyuncs.com", + "vpc": "ecs-vpc.cn-wulanchabu.aliyuncs.com" + }, + { + "regionId": "cn-shenzhen-finance-1", + "regionName": "华南1 金融云", + "areaId": "industryCloud", + "areaName": "行业云", + "public": "ecs-cn-hangzhou.aliyuncs.com", + "vpc": "ecs-vpc.cn-shenzhen-finance-1.aliyuncs.com" + }, + { + "regionId": "cn-shenzhen", + "regionName": "华南1(深圳)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-shenzhen.aliyuncs.com", + "vpc": "ecs-vpc.cn-shenzhen.aliyuncs.com" + }, + { + "regionId": "cn-shanghai-finance-1", + "regionName": "华东2 金融云", + "areaId": "industryCloud", + "areaName": "行业云", + "public": "ecs-cn-hangzhou.aliyuncs.com", + "vpc": "ecs-vpc.cn-shanghai-finance-1.aliyuncs.com" + }, + { + "regionId": "cn-shanghai", + "regionName": "华东2(上海)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-shanghai.aliyuncs.com", + "vpc": "ecs-vpc.cn-shanghai.aliyuncs.com" + }, + { + "regionId": "cn-qingdao", + "regionName": "华北1(青岛)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-qingdao.aliyuncs.com", + "vpc": "ecs-vpc.cn-qingdao.aliyuncs.com" + }, + { + "regionId": "cn-nanjing", + "regionName": "华东5(南京-本地地域)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-nanjing.aliyuncs.com", + "vpc": "ecs-vpc.cn-nanjing.aliyuncs.com" + }, + { + "regionId": "cn-huhehaote", + "regionName": "华北5(呼和浩特)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-huhehaote.aliyuncs.com", + "vpc": "ecs-vpc.cn-huhehaote.aliyuncs.com" + }, + { + "regionId": "cn-hongkong", + "regionName": "中国香港", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-hongkong.aliyuncs.com", + "vpc": "ecs-vpc.cn-hongkong.aliyuncs.com" + }, + { + "regionId": "cn-heyuan", + "regionName": "华南2(河源)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-heyuan.aliyuncs.com", + "vpc": "ecs-vpc.cn-heyuan.aliyuncs.com" + }, + { + "regionId": "cn-hangzhou-finance", + "regionName": "华东1 金融云", + "areaId": "industryCloud", + "areaName": "行业云", + "public": "ecs.aliyuncs.com" + }, + { + "regionId": "cn-hangzhou", + "regionName": "华东1(杭州)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs-cn-hangzhou.aliyuncs.com", + "vpc": "ecs-vpc.cn-hangzhou.aliyuncs.com" + }, + { + "regionId": "cn-guangzhou", + "regionName": "华南3(广州)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-guangzhou.aliyuncs.com", + "vpc": "ecs-vpc.cn-guangzhou.aliyuncs.com" + }, + { + "regionId": "cn-fuzhou", + "regionName": "华东6(福州-本地地域)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-fuzhou.aliyuncs.com", + "vpc": "ecs-vpc.cn-fuzhou.aliyuncs.com" + }, + { + "regionId": "cn-chengdu", + "regionName": "西南1(成都)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-chengdu.aliyuncs.com", + "vpc": "ecs-vpc.cn-chengdu.aliyuncs.com" + }, + { + "regionId": "cn-beijing-finance-1", + "regionName": "华北2 金融云(邀测)", + "areaId": "industryCloud", + "areaName": "行业云", + "public": "ecs.cn-beijing-finance-1.aliyuncs.com", + "vpc": "ecs-vpc.cn-beijing-finance-1.aliyuncs.com" + }, + { + "regionId": "cn-beijing", + "regionName": "华北2(北京)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.cn-beijing.aliyuncs.com", + "vpc": "ecs-vpc.cn-beijing.aliyuncs.com" + }, + { + "regionId": "ap-southeast-7", + "regionName": "泰国(曼谷)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-southeast-7.aliyuncs.com", + "vpc": "ecs-vpc.ap-southeast-7.aliyuncs.com" + }, + { + "regionId": "ap-southeast-6", + "regionName": "菲律宾(马尼拉)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-southeast-6.aliyuncs.com", + "vpc": "ecs-vpc.ap-southeast-6.aliyuncs.com" + }, + { + "regionId": "ap-southeast-5", + "regionName": "印度尼西亚(雅加达)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-southeast-5.aliyuncs.com", + "vpc": "ecs-vpc.ap-southeast-5.aliyuncs.com" + }, + { + "regionId": "ap-southeast-3", + "regionName": "马来西亚(吉隆坡)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-southeast-3.aliyuncs.com", + "vpc": "ecs-vpc.ap-southeast-3.aliyuncs.com" + }, + { + "regionId": "ap-southeast-2", + "regionName": "澳大利亚(悉尼)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-southeast-2.aliyuncs.com", + "vpc": "ecs-vpc.ap-southeast-2.aliyuncs.com" + }, + { + "regionId": "ap-southeast-1", + "regionName": "新加坡", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-southeast-1.aliyuncs.com", + "vpc": "ecs-vpc.ap-southeast-1.aliyuncs.com" + }, + { + "regionId": "ap-south-1", + "regionName": "印度(孟买)", + "areaId": "middleEast", + "areaName": "中东与印度", + "public": "ecs.ap-south-1.aliyuncs.com", + "vpc": "ecs-vpc.ap-south-1.aliyuncs.com" + }, + { + "regionId": "ap-northeast-2", + "regionName": "韩国(首尔)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-northeast-2.aliyuncs.com", + "vpc": "ecs-vpc.ap-northeast-2.aliyuncs.com" + }, + { + "regionId": "ap-northeast-1", + "regionName": "日本(东京)", + "areaId": "asiaPacific", + "areaName": "亚太", + "public": "ecs.ap-northeast-1.aliyuncs.com", + "vpc": "ecs-vpc.ap-northeast-1.aliyuncs.com" + } +] diff --git a/media/src/mocks/makeCode.ts b/media/src/mocks/makeCode.ts new file mode 100644 index 0000000..9e2ed4d --- /dev/null +++ b/media/src/mocks/makeCode.ts @@ -0,0 +1,23 @@ +export const codes = { + "demoSdk": { + "typescript": "// This file is auto-generated, don't edit it\n// 依赖的模块可通过下载工程中的模块依赖文件或右上角的获取 SDK 依赖信息查看\nimport Ecs20140526, * as $Ecs20140526 from '@alicloud/ecs20140526';\nimport OpenApi, * as $OpenApi from '@alicloud/openapi-client';\nimport Util, * as $Util from '@alicloud/tea-util';\nimport * as $tea from '@alicloud/tea-typescript';\n\n\nexport default class Client {\n\n /**\n * 使用AK&SK初始化账号Client\n * @param accessKeyId\n * @param accessKeySecret\n * @return Client\n * @throws Exception\n */\n static createClient(accessKeyId: string, accessKeySecret: string): Ecs20140526 {\n let config = new $OpenApi.Config({\n // 必填,您的 AccessKey ID\n accessKeyId: accessKeyId,\n // 必填,您的 AccessKey Secret\n accessKeySecret: accessKeySecret,\n });\n // Endpoint 请参考 https://api.aliyun.com/product/Ecs\n config.endpoint = `ecs.cn-qingdao.aliyuncs.com`;\n return new Ecs20140526(config);\n }\n\n static async main(args: string[]): Promise {\n // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378664.html\n let client = Client.createClient(process.env['ALIBABA_CLOUD_ACCESS_KEY_ID'], process.env['ALIBABA_CLOUD_ACCESS_KEY_SECRET']);\n let runInstancesRequest = new $Ecs20140526.RunInstancesRequest({\n regionId: \"cn-qingdao\",\n });\n let runtime = new $Util.RuntimeOptions({ });\n try {\n // 复制代码运行请自行打印 API 的返回值\n await client.runInstancesWithOptions(runInstancesRequest, runtime);\n } catch (error) {\n // 错误 message\n console.log(error.message);\n // 诊断地址\n console.log(error.data[\"Recommend\"]);\n Util.assertAsString(error.message);\n } \n }\n\n}\n\nClient.main(process.argv.slice(2));", + "java": "// This file is auto-generated, don't edit it. Thanks.\npackage com.aliyun.sample;\n\nimport com.aliyun.tea.*;\n\npublic class Sample {\n\n /**\n * 使用AK&SK初始化账号Client\n * @param accessKeyId\n * @param accessKeySecret\n * @return Client\n * @throws Exception\n */\n public static com.aliyun.ecs20140526.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {\n com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()\n // 必填,您的 AccessKey ID\n .setAccessKeyId(accessKeyId)\n // 必填,您的 AccessKey Secret\n .setAccessKeySecret(accessKeySecret);\n // Endpoint 请参考 https://api.aliyun.com/product/Ecs\n config.endpoint = \"ecs.cn-qingdao.aliyuncs.com\";\n return new com.aliyun.ecs20140526.Client(config);\n }\n\n public static void main(String[] args_) throws Exception {\n java.util.List args = java.util.Arrays.asList(args_);\n // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html\n com.aliyun.ecs20140526.Client client = Sample.createClient(System.getenv(\"ALIBABA_CLOUD_ACCESS_KEY_ID\"), System.getenv(\"ALIBABA_CLOUD_ACCESS_KEY_SECRET\"));\n com.aliyun.ecs20140526.models.RunInstancesRequest runInstancesRequest = new com.aliyun.ecs20140526.models.RunInstancesRequest()\n .setRegionId(\"cn-qingdao\");\n com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();\n try {\n // 复制代码运行请自行打印 API 的返回值\n client.runInstancesWithOptions(runInstancesRequest, runtime);\n } catch (TeaException error) {\n // 错误 message\n System.out.println(error.getMessage());\n // 诊断地址\n System.out.println(error.getData().get(\"Recommend\"));\n com.aliyun.teautil.Common.assertAsString(error.message);\n } catch (Exception _error) {\n TeaException error = new TeaException(_error.getMessage(), _error);\n // 错误 message\n System.out.println(error.getMessage());\n // 诊断地址\n System.out.println(error.getData().get(\"Recommend\"));\n com.aliyun.teautil.Common.assertAsString(error.message);\n } \n }\n}\n", + "php": " $accessKeyId,\n // 必填,您的 AccessKey Secret\n \"accessKeySecret\" => $accessKeySecret\n ]);\n // Endpoint 请参考 https://api.aliyun.com/product/Ecs\n $config->endpoint = \"ecs.cn-qingdao.aliyuncs.com\";\n return new Ecs($config);\n }\n\n /**\n * @param string[] $args\n * @return void\n */\n public static function main($args){\n // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/311677.html\n $client = self::createClient(getenv(\"ALIBABA_CLOUD_ACCESS_KEY_ID\"), getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'));\n $runInstancesRequest = new RunInstancesRequest([\n \"regionId\" => \"cn-qingdao\"\n ]);\n $runtime = new RuntimeOptions([]);\n try {\n // 复制代码运行请自行打印 API 的返回值\n $client->runInstancesWithOptions($runInstancesRequest, $runtime);\n }\n catch (Exception $error) {\n if (!($error instanceof TeaError)) {\n $error = new TeaError([], $error->getMessage(), $error->getCode(), $error);\n }\n // 错误 message\n var_dump($error->message);\n // 诊断地址\n var_dump($error->data[\"Recommend\"]);\n Utils::assertAsString($error->message);\n }\n }\n}\n$path = __DIR__ . \\DIRECTORY_SEPARATOR . '..' . \\DIRECTORY_SEPARATOR . 'vendor' . \\DIRECTORY_SEPARATOR . 'autoload.php';\nif (file_exists($path)) {\n require_once $path;\n}\nSample::main(array_slice($argv, 1));\n", + "python": "# -*- coding: utf-8 -*-\n# This file is auto-generated, don't edit it. Thanks.\nimport os\nimport sys\n\nfrom typing import List\n\nfrom alibabacloud_ecs20140526.client import Client as Ecs20140526Client\nfrom alibabacloud_tea_openapi import models as open_api_models\nfrom alibabacloud_ecs20140526 import models as ecs_20140526_models\nfrom alibabacloud_tea_util import models as util_models\nfrom alibabacloud_tea_util.client import Client as UtilClient\n\n\nclass Sample:\n def __init__(self):\n pass\n\n @staticmethod\n def create_client(\n access_key_id: str,\n access_key_secret: str,\n ) -> Ecs20140526Client:\n \"\"\"\n 使用AK&SK初始化账号Client\n @param access_key_id:\n @param access_key_secret:\n @return: Client\n @throws Exception\n \"\"\"\n config = open_api_models.Config(\n # 必填,您的 AccessKey ID,\n access_key_id=access_key_id,\n # 必填,您的 AccessKey Secret,\n access_key_secret=access_key_secret\n )\n # Endpoint 请参考 https://api.aliyun.com/product/Ecs\n config.endpoint = f'ecs.cn-qingdao.aliyuncs.com'\n return Ecs20140526Client(config)\n\n @staticmethod\n def main(\n args: List[str],\n ) -> None:\n # 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n # 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html\n client = Sample.create_client(os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'], os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'])\n run_instances_request = ecs_20140526_models.RunInstancesRequest(\n region_id='cn-qingdao'\n )\n runtime = util_models.RuntimeOptions()\n try:\n # 复制代码运行请自行打印 API 的返回值\n client.run_instances_with_options(run_instances_request, runtime)\n except Exception as error:\n # 错误 message\n print(error.message)\n # 诊断地址\n print(error.data.get(\"Recommend\"))\n UtilClient.assert_as_string(error.message)\n\n @staticmethod\n async def main_async(\n args: List[str],\n ) -> None:\n # 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n # 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html\n client = Sample.create_client(os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'], os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'])\n run_instances_request = ecs_20140526_models.RunInstancesRequest(\n region_id='cn-qingdao'\n )\n runtime = util_models.RuntimeOptions()\n try:\n # 复制代码运行请自行打印 API 的返回值\n await client.run_instances_with_options_async(run_instances_request, runtime)\n except Exception as error:\n # 错误 message\n print(error.message)\n # 诊断地址\n print(error.data.get(\"Recommend\"))\n UtilClient.assert_as_string(error.message)\n\n\nif __name__ == '__main__':\n Sample.main(sys.argv[1:])\n", + "go": "// This file is auto-generated, don't edit it. Thanks.\npackage main\n\nimport (\n \"encoding/json\"\n \"strings\"\n \"fmt\"\n \"os\"\n ecs20140526 \"github.com/alibabacloud-go/ecs-20140526/v3/client\"\n openapi \"github.com/alibabacloud-go/darabonba-openapi/v2/client\"\n util \"github.com/alibabacloud-go/tea-utils/v2/service\"\n \"github.com/alibabacloud-go/tea/tea\"\n)\n\n\n/**\n * 使用AK&SK初始化账号Client\n * @param accessKeyId\n * @param accessKeySecret\n * @return Client\n * @throws Exception\n */\nfunc CreateClient (accessKeyId *string, accessKeySecret *string) (_result *ecs20140526.Client, _err error) {\n config := &openapi.Config{\n // 必填,您的 AccessKey ID\n AccessKeyId: accessKeyId,\n // 必填,您的 AccessKey Secret\n AccessKeySecret: accessKeySecret,\n }\n // Endpoint 请参考 https://api.aliyun.com/product/Ecs\n config.Endpoint = tea.String(\"ecs.cn-qingdao.aliyuncs.com\")\n _result = &ecs20140526.Client{}\n _result, _err = ecs20140526.NewClient(config)\n return _result, _err\n}\n\nfunc _main (args []*string) (_err error) {\n // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378661.html\n client, _err := CreateClient(tea.String(os.Getenv(\"ALIBABA_CLOUD_ACCESS_KEY_ID\")), tea.String(os.Getenv(\"ALIBABA_CLOUD_ACCESS_KEY_SECRET\")))\n if _err != nil {\n return _err\n }\n\n runInstancesRequest := &ecs20140526.RunInstancesRequest{\n RegionId: tea.String(\"cn-qingdao\"),\n }\n runtime := &util.RuntimeOptions{}\n tryErr := func()(_e error) {\n defer func() {\n if r := tea.Recover(recover()); r != nil {\n _e = r\n }\n }()\n // 复制代码运行请自行打印 API 的返回值\n _, _err = client.RunInstancesWithOptions(runInstancesRequest, runtime)\n if _err != nil {\n return _err\n }\n\n return nil\n }()\n\n if tryErr != nil {\n var error = &tea.SDKError{}\n if _t, ok := tryErr.(*tea.SDKError); ok {\n error = _t\n } else {\n error.Message = tea.String(tryErr.Error())\n }\n // 错误 message\n fmt.Println(tea.StringValue(error.Message))\n // 诊断地址\n var data interface{}\n d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data)))\n d.Decode(&data)\n if m, ok := data.(map[string]interface{}); ok {\n recommend, _ := m[\"Recommend\"]\n fmt.Println(recommend)\n }\n _, _err = util.AssertAsString(error.Message)\n if _err != nil {\n return _err\n }\n }\n return _err\n}\n\n\nfunc main() {\n err := _main(tea.StringSlice(os.Args[1:]))\n if err != nil {\n panic(err)\n }\n}\n", + "python2": "# -*- coding: utf-8 -*-\n# This file is auto-generated, don't edit it. Thanks.\nfrom __future__ import unicode_literals\n\nimport os\nimport sys\n\nfrom alibabacloud_ecs20140526.client import Client as Ecs20140526Client\nfrom alibabacloud_tea_openapi import models as open_api_models\nfrom alibabacloud_ecs20140526 import models as ecs_20140526_models\nfrom alibabacloud_tea_util import models as util_models\nfrom alibabacloud_tea_util.client import Client as UtilClient\n\n\nclass Sample(object):\n def __init__(self):\n pass\n\n @staticmethod\n def create_client(access_key_id, access_key_secret):\n \"\"\"\n 使用AK&SK初始化账号Client\n\n @type access_key_id: str\n @param access_key_id:\n\n @type access_key_secret: str\n @param access_key_secret:\n\n @return: Client\n @throws Exception\n \"\"\"\n config = open_api_models.Config(\n # 必填,您的 AccessKey ID,\n access_key_id=access_key_id,\n # 必填,您的 AccessKey Secret,\n access_key_secret=access_key_secret\n )\n # Endpoint 请参考 https://api.aliyun.com/product/Ecs\n config.endpoint = 'ecs.cn-qingdao.aliyuncs.com'\n return Ecs20140526Client(config)\n\n @staticmethod\n def main(args):\n # 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n # 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html\n client = Sample.create_client(os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'], os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'])\n run_instances_request = ecs_20140526_models.RunInstancesRequest(\n region_id='cn-qingdao'\n )\n runtime = util_models.RuntimeOptions()\n try:\n # 复制代码运行请自行打印 API 的返回值\n client.run_instances_with_options(run_instances_request, runtime)\n except Exception as error:\n # 错误 message\n print error.message\n # 诊断地址\n print error.data.get(\"Recommend\")\n UtilClient.assert_as_string(error.message)\n\n\nif __name__ == '__main__':\n Sample.main(sys.argv[1:])\n", + "csharp": "// This file is auto-generated, don't edit it. Thanks.\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Threading.Tasks;\n\nusing Tea;\nusing Tea.Utils;\n\n\nnamespace AlibabaCloud.SDK.Sample\n{\n public class Sample \n {\n\n /**\n * 使用AK&SK初始化账号Client\n * @param accessKeyId\n * @param accessKeySecret\n * @return Client\n * @throws Exception\n */\n public static AlibabaCloud.SDK.Ecs20140526.Client CreateClient(string accessKeyId, string accessKeySecret)\n {\n AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config\n {\n // 必填,您的 AccessKey ID\n AccessKeyId = accessKeyId,\n // 必填,您的 AccessKey Secret\n AccessKeySecret = accessKeySecret,\n };\n // Endpoint 请参考 https://api.aliyun.com/product/Ecs\n config.Endpoint = \"ecs.cn-qingdao.aliyuncs.com\";\n return new AlibabaCloud.SDK.Ecs20140526.Client(config);\n }\n\n public static void Main(string[] args)\n {\n // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。\n // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378671.html\n AlibabaCloud.SDK.Ecs20140526.Client client = CreateClient(Environment.GetEnvironmentVariable(\"ALIBABA_CLOUD_ACCESS_KEY_ID\"), Environment.GetEnvironmentVariable(\"ALIBABA_CLOUD_ACCESS_KEY_SECRET\"));\n AlibabaCloud.SDK.Ecs20140526.Models.RunInstancesRequest runInstancesRequest = new AlibabaCloud.SDK.Ecs20140526.Models.RunInstancesRequest\n {\n RegionId = \"cn-qingdao\",\n };\n AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();\n try\n {\n // 复制代码运行请自行打印 API 的返回值\n client.RunInstancesWithOptions(runInstancesRequest, runtime);\n }\n catch (TeaException error)\n {\n // 错误 message\n Console.WriteLine(error.Message);\n // 诊断地址\n Console.WriteLine(error.Data[\"Recommend\"]);\n AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);\n }\n catch (Exception _error)\n {\n TeaException error = new TeaException(new Dictionary\n {\n { \"message\", _error.Message }\n });\n // 错误 message\n Console.WriteLine(error.Message);\n // 诊断地址\n Console.WriteLine(error.Data[\"Recommend\"]);\n AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message);\n }\n }\n\n\n }\n}\n", + "swift": "#!/usr/bin/env xcrun swift\n\nimport Cocoa\nimport Foundation\nimport Tea\nimport AlibabacloudEcs20140526\nimport AlibabacloudOpenApi\nimport TeaUtils\n\nopen class Client {\n public static func createClient(_ accessKeyId: String?, _ accessKeySecret: String?) throws -> AlibabacloudEcs20140526.Client {\n var config: AlibabacloudOpenApi.Config = AlibabacloudOpenApi.Config([\n \"accessKeyId\": accessKeyId as! String,\n \"accessKeySecret\": accessKeySecret as! String\n ])\n config.endpoint = \"ecs.cn-qingdao.aliyuncs.com\"\n return AlibabacloudEcs20140526.Client(config)\n }\n\n @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)\n public static func main(_ args: [String]?) async throws -> Void {\n var client: AlibabacloudEcs20140526.Client = try Client.createClient(ProcessInfo.processInfo.environment[\"ALIBABA_CLOUD_ACCESS_KEY_ID\"], ProcessInfo.processInfo.environment[\"ALIBABA_CLOUD_ACCESS_KEY_SECRET\"])\n var runInstancesRequest: AlibabacloudEcs20140526.RunInstancesRequest = AlibabacloudEcs20140526.RunInstancesRequest([\n \"regionId\": \"cn-qingdao\"\n ])\n var runtime: TeaUtils.RuntimeOptions = TeaUtils.RuntimeOptions([:])\n do {\n try await client.runInstancesWithOptions(runInstancesRequest as! AlibabacloudEcs20140526.RunInstancesRequest, runtime as! TeaUtils.RuntimeOptions)\n }\n catch {\n if error is Tea.TeaError {\n try TeaUtils.Client.assertAsString(error.message)\n } else {\n throw error\n }\n }\n }\n}\n\nClient.main(CommandLine.arguments)\n", + "java-async": "// This file is auto-generated, don't edit it. Thanks.\npackage demo;\n\nimport com.aliyun.auth.credentials.Credential;\nimport com.aliyun.auth.credentials.provider.StaticCredentialProvider;\nimport com.aliyun.core.http.HttpClient;\nimport com.aliyun.core.http.HttpMethod;\nimport com.aliyun.core.http.ProxyOptions;\nimport com.aliyun.httpcomponent.httpclient.ApacheAsyncHttpClientBuilder;\nimport com.aliyun.sdk.service.ecs20140526.models.*;\nimport com.aliyun.sdk.service.ecs20140526.*;\nimport com.google.gson.Gson;\nimport darabonba.core.RequestConfiguration;\nimport darabonba.core.client.ClientOverrideConfiguration;\nimport darabonba.core.utils.CommonUtil;\nimport darabonba.core.TeaPair;\n\n//import javax.net.ssl.KeyManager;\n//import javax.net.ssl.X509TrustManager;\nimport java.net.InetSocketAddress;\nimport java.time.Duration;\nimport java.util.*;\nimport java.util.concurrent.CompletableFuture;\n\npublic class RunInstances {\n public static void main(String[] args) throws Exception {\n\n // HttpClient Configuration\n /*HttpClient httpClient = new ApacheAsyncHttpClientBuilder()\n .connectionTimeout(Duration.ofSeconds(10)) // Set the connection timeout time, the default is 10 seconds\n .responseTimeout(Duration.ofSeconds(10)) // Set the response timeout time, the default is 20 seconds\n .maxConnections(128) // Set the connection pool size\n .maxIdleTimeOut(Duration.ofSeconds(50)) // Set the connection pool timeout, the default is 30 seconds\n // Configure the proxy\n .proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress(\"\", 9001))\n .setCredentials(\"\", \"\"))\n // If it is an https connection, you need to configure the certificate, or ignore the certificate(.ignoreSSL(true))\n .x509TrustManagers(new X509TrustManager[]{})\n .keyManagers(new KeyManager[]{})\n .ignoreSSL(false)\n .build();*/\n\n // Configure Credentials authentication information, including ak, secret, token\n StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()\n // Please ensure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.\n .accessKeyId(System.getenv(\"ALIBABA_CLOUD_ACCESS_KEY_ID\"))\n .accessKeySecret(System.getenv(\"ALIBABA_CLOUD_ACCESS_KEY_SECRET\"))\n //.securityToken(System.getenv(\"ALIBABA_CLOUD_SECURITY_TOKEN\")) // use STS token\n .build());\n\n // Configure the Client\n AsyncClient client = AsyncClient.builder()\n .region(\"cn-qingdao\") // Region ID\n //.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)\n .credentialsProvider(provider)\n //.serviceConfiguration(Configuration.create()) // Service-level configuration\n // Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.\n .overrideConfiguration(\n ClientOverrideConfiguration.create()\n // Endpoint 请参考 https://api.aliyun.com/product/Ecs\n .setEndpointOverride(\"ecs.cn-qingdao.aliyuncs.com\")\n //.setConnectTimeout(Duration.ofSeconds(30))\n )\n .build();\n\n // Parameter settings for API request\n RunInstancesRequest runInstancesRequest = RunInstancesRequest.builder()\n .regionId(\"cn-qingdao\")\n // Request-level configuration rewrite, can set Http request parameters, etc.\n // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))\n .build();\n\n // Asynchronously get the return value of the API request\n CompletableFuture response = client.runInstances(runInstancesRequest);\n // Synchronously get the return value of the API request\n RunInstancesResponse resp = response.get();\n System.out.println(new Gson().toJson(resp));\n // Asynchronous processing of return values\n /*response.thenAccept(resp -> {\n System.out.println(new Gson().toJson(resp));\n }).exceptionally(throwable -> { // Handling exceptions\n System.out.println(throwable.getMessage());\n return null;\n });*/\n\n // Finally, close the client\n client.close();\n }\n\n}\n", + "dependencies": "\n\n 4.0.0\n com.aliyun\n sample\n 1.0.0\n jar\n sample\n \n \n The Apache License, Version 2.0\n http://www.apache.org/licenses/LICENSE-2.0.txt\n \n \n \n \n aliyunproducts\n Aliyun SDK\n aliyunsdk@aliyun.com\n \n \n \n 1.8\n 8\n 8\n \n \n \n com.aliyun\n alibabacloud-ecs20140526\n 2.0.12\n \n \n com.aliyun\n aliyun-gateway-pop\n 0.1.5-beta\n \n \n com.aliyun\n aliyun-gateway-oss\n 0.1.5-beta\n \n \n com.aliyun\n aliyun-gateway-sls\n 0.1.5-beta\n \n \n \n \n \n org.apache.maven.plugins\n maven-compiler-plugin\n 3.6.1\n \n ${maven.compiler.source}\n ${maven.compiler.target}\n \n \n \n \n" + }, + "apiInfo": { + "apiStyle": "RPC", + "product": "Ecs", + "method": "POST,GET", + "apiVersion": "2014-05-26", + "apiName": "RunInstances", + "regionId": "cn-qingdao" + }, + "cost": 628 +} \ No newline at end of file diff --git a/media/src/mocks/openApiResponse.ts b/media/src/mocks/openApiResponse.ts index 76e7b20..5f085bd 100644 --- a/media/src/mocks/openApiResponse.ts +++ b/media/src/mocks/openApiResponse.ts @@ -1,5 +1,6 @@ export const apiResponse = { "format": "json", + "cost": 300, "result": { "RequestId": "9BE1875B-EE52-501D-AD6E-BF0EEC4E1660", "Regions": { diff --git a/media/src/mocks/routerMeta.ts b/media/src/mocks/routerMeta.ts index 343d0a8..1d871e2 100644 --- a/media/src/mocks/routerMeta.ts +++ b/media/src/mocks/routerMeta.ts @@ -1,17 +1,21 @@ export const routerMeta = { - "specName": "ocr-api::2021-07-07", + "specName": "Oss::2019-05-17", "modName": "", "spec": { + "consumes": [ + "application/xml" + ], "deprecated": false, - "description": "#### 本接口适用场景\n* 阿里云通用手写体识别,是阿里云官方自研OCR文字识别产品,适用于获取手写体书面形式的文字场景,适用于各类手写笔记、板书等。\n* 阿里云OCR产品基于阿里巴巴达摩院强大的AI技术及海量数据,历经多年沉淀打磨,具有服务稳定、操作简易、实时性高、能力全面等几大优势。\n* 本接口图片示例\n

\n\n#### 本接口核心能力\n \n|分类 |概述|\n|---|---------|\n|多文字形式|支持中文手写体、英文手写体、数字手写体。|\n|图像增强|默认支持图像增强,包括图像自动旋转、畸变自动矫正、模糊图片自动增强等能力。|\n|多类型覆盖|支持模糊、光照不均、透视畸变、任意背景等低质量图像识别。|\n|高精度识别|总体识别准确率可达98%。|\n\n#### 如何使用本接口\n\n|步骤|概述|\n|--|---|\n|1|开通 [通用文字识别](https://common-buy.aliyun.com?commodityCode=ocr_general_public_cn) 服务。开通服务前后,您可以通过[体验馆](https://duguang.aliyun.com/experience?type=universal&subtype=shouxie#intro)免费体验本功能识别效果。|\n|2|购买[通用手写体识别资源包](https://common-buy.aliyun.com/?commodityCode=ocr_general_dp_cn&request=%7B%22ord_time%22:%221:Year%22,%22order_num%22:1,%22pack%22:%22ocr_general_dp_cn_20211103172431_0249%22,%22flowout_spec%22:%22500%22%7D)。本API会赠送免费额度,可使用免费额度测试。|\n|3|可以参照[调试页面](https://next.api.aliyun.com/api/ocr-api/2021-07-07/RecognizeHandwriting?sdkStyle=dara)提供的代码示例完成API接入开发。接入完成后,调用API获取识别结果。如果使用子账号调用接口,需要阿里云账号(主账号)对RAM账号进行授权。创建RAM用户的具体操作,请参考:[创建RAM用户。](https://help.aliyun.com/document_detail/93720.html)文字识别服务提供一种系统授权策略,即**AliyunOCRFullAccess**。具体授权操作,请参见[在用户页面为RAM用户授权。](https://help.aliyun.com/document_detail/116146.html)|\n\n#### 重要提示\n|类型|概述|\n|----|-------------------|\n|图片格式|
  • 本接口支持:PNG、JPG、JPEG、BMP、GIF、TIFF、WebP。暂不支持PDF格式。
|\n|图片尺寸|
  • 图片长宽需要大于15像素,小于8192像素。
  • 长宽比需要小于50。
  • 如需达到较好识别效果,建议长宽均大于500px。
  • 图片尺寸过小,会影响识别精度。图片内单字大小在10-50px内时,识别效果较好。
|\n|图片大小|
  • 图片二进制文件不能超过10MB。
  • 图片过大会影响接口响应速度,建议使用小于1.5M图片进行识别,且通过传图片URL的方式调用接口。
|\n|其他提示|
  • 接口响应速度和图片中的文字数量有关,如果图片中文字数量越多,接口响应可能越慢。
  • 接口会自动处理反光、扭曲等干扰信息,但会影响精度。请尽量选择清晰度高、无反光、无扭曲的图片。
|\n|相关能力|
  • [云市场手写体识别。](https://market.aliyun.com/products/57124001/cmapi00040832.html?#sku=yuncode3483200001)
|", + "description": "- 此操作要求您对该Object有读权限。\n- 正确执行时,该API返回206。如果SQL语句不正确,或者和文件不匹配,则会返回400错误。\n- 关于SelectObject的功能介绍请参见[使用SelectObject查询文件](https://help.aliyun.com/document_detail/106082.html)。", "ext": { "methods": [ - "get", "post" ], "operationType": "read", - "responseDemo": "[{\"type\":\"json\",\"example\":\"{\\n \\\"RequestId\\\": \\\"43A29C77-405E-4CC0-BC55-EE694AD00655\\\",\\n \\\"Data\\\": \\\"{\\\\\\\"content\\\\\\\":\\\\\\\"炼句 提问方式 1.请赏析诗歌某一联(句) 2.赏析某一联(句)的妙处 3.请赏析诗歌某、角度抒胸意、借景抒情、托物\\\\\\\",\\\\\\\"height\\\\\\\":1277,\\\\\\\"orgHeight\\\\\\\":1277,\\\\\\\"orgWidth\\\\\\\":1080,\\\\\\\"prism_version\\\\\\\":\\\\\\\"1.0.9\\\\\\\",\\\\\\\"prism_wnum\\\\\\\":26,\\\\\\\"prism_wordsInfo\\\\\\\":[{\\\\\\\"angle\\\\\\\":-87,\\\\\\\"direction\\\\\\\":0,\\\\\\\"height\\\\\\\":83,\\\\\\\"pos\\\\\\\":[{\\\\\\\"x\\\\\\\":177,\\\\\\\"y\\\\\\\":56},{\\\\\\\"x\\\\\\\":260,\\\\\\\"y\\\\\\\":60},{\\\\\\\"x\\\\\\\":259,\\\\\\\"y\\\\\\\":88},{\\\\\\\"x\\\\\\\":176,\\\\\\\"y\\\\\\\":84}],\\\\\\\"prob\\\\\\\":96,\\\\\\\"width\\\\\\\":28,\\\\\\\"word\\\\\\\":\\\\\\\"炼句\\\\\\\",\\\\\\\"x\\\\\\\":203,\\\\\\\"y\\\\\\\":30}],\\\\\\\"width\\\\\\\":1080}\\\",\\n \\\"Code\\\": \\\"200\\\",\\n \\\"Message\\\": \\\"message\\\"\\n}\",\"errorExample\":\"\"},{\"type\":\"xml\",\"example\":\"\\n 4AA3FA7B-CB2D-4314-B812-A598B540BADA\\n {\\\"content\\\":\\\"炼句 提问方式 1.请赏析诗歌某一联(句) 2.赏析某一联(句)的妙处 3.请赏析诗歌某一联1句)的表达效果 常规答题思路 1.手法: 1写景的句子侧重于写景手法(感官、角度.动静、虚实、典型画面、寓情于景等) ②写人的句子侧重于写人手法(动作、心理、肖像、细节等) ③抒情的句子侧重于抒情方式(直抒胸意、借景抒情、托物言志、用典抒情、 借古讽今等) 2.内容:写出…内容,描绘…的情景(画面),体现.特点 3.情感:表达了……的情感心理),或者渲染了…..的意境氛围 4.结构: 照应1与标题或者前后某内容照应),铺垫(为下文作了铺垫) 说明 1.所考的是诗歌的第一句,有时要考虑:点明时令,总领全诗,奠定情感基调 所考的是诗歌的最后一句,有时要考虑:言有尽而意无穷,给读者留下 想象空间。 2.如果该句没有什么突出手法,那么我们的精力应该花在内容、情感结构上 题型迁移 二 提问方式:某句诗有什么作用 作用题的答题模式约等于“炼句题” 说明:“炼句“与某句诗作用”的区别 “炼句”侧重于本句的手法,而“某句诗作用“则是侧重于结构与内容。 \\\",\\\"height\\\":1277,\\\"orgHeight\\\":1277,\\\"orgWidth\\\":1080,\\\"prism_version\\\":\\\"1.0.9\\\",\\\"prism_wnum\\\":26,\\\"prism_wordsInfo\\\":[{\\\"angle\\\":-87,\\\"direction\\\":0,\\\"height\\\":83,\\\"pos\\\":[{\\\"x\\\":177,\\\"y\\\":56},{\\\"x\\\":260,\\\"y\\\":60},{\\\"x\\\":259,\\\"y\\\":88},{\\\"x\\\":176,\\\"y\\\":84}],\\\"prob\\\":96,\\\"width\\\":28,\\\"word\\\":\\\"炼句\\\",\\\"x\\\":203,\\\"y\\\":30},{\\\"angle\\\":-87,\\\"direction\\\":0,\\\"height\\\":115,\\\"pos\\\":[{\\\"x\\\":172,\\\"y\\\":114},{\\\"x\\\":287,\\\"y\\\":120},{\\\"x\\\":286,\\\"y\\\":146},{\\\"x\\\":171,\\\"y\\\":141}],\\\"prob\\\":98,\\\"width\\\":27,\\\"word\\\":\\\"提问方式\\\",\\\"x\\\":215,\\\"y\\\":71},{\\\"angle\\\":-89,\\\"direction\\\":0,\\\"height\\\":280,\\\"pos\\\":[{\\\"x\\\":287,\\\"y\\\":119},{\\\"x\\\":567,\\\"y\\\":119},{\\\"x\\\":567,\\\"y\\\":146},{\\\"x\\\":287,\\\"y\\\":146}],\\\"prob\\\":97,\\\"width\\\":26,\\\"word\\\":\\\"1.请赏析诗歌某一联(句)\\\",\\\"x\\\":414,\\\"y\\\":-8},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":27,\\\"pos\\\":[{\\\"x\\\":286,\\\"y\\\":167},{\\\"x\\\":576,\\\"y\\\":164},{\\\"x\\\":576,\\\"y\\\":192},{\\\"x\\\":286,\\\"y\\\":194}],\\\"prob\\\":98,\\\"width\\\":289,\\\"word\\\":\\\"2.赏析某一联(句)的妙处\\\",\\\"x\\\":286,\\\"y\\\":165},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":30,\\\"pos\\\":[{\\\"x\\\":285,\\\"y\\\":213},{\\\"x\\\":667,\\\"y\\\":207},{\\\"x\\\":667,\\\"y\\\":236},{\\\"x\\\":285,\\\"y\\\":242}],\\\"prob\\\":96,\\\"width\\\":382,\\\"word\\\":\\\"3.请赏析诗歌某一联1句)的表达效果\\\",\\\"x\\\":285,\\\"y\\\":209},{\\\"angle\\\":-90,\\\"direction\\\":0,\\\"height\\\":156,\\\"pos\\\":[{\\\"x\\\":165,\\\"y\\\":284},{\\\"x\\\":321,\\\"y\\\":284},{\\\"x\\\":321,\\\"y\\\":310},{\\\"x\\\":165,\\\"y\\\":310}],\\\"prob\\\":98,\\\"width\\\":26,\\\"word\\\":\\\"常规答题思路\\\",\\\"x\\\":231,\\\"y\\\":219},{\\\"angle\\\":-2,\\\"direction\\\":0,\\\"height\\\":26,\\\"pos\\\":[{\\\"x\\\":357,\\\"y\\\":288},{\\\"x\\\":441,\\\"y\\\":286},{\\\"x\\\":442,\\\"y\\\":312},{\\\"x\\\":358,\\\"y\\\":314}],\\\"prob\\\":97,\\\"width\\\":84,\\\"word\\\":\\\"1.手法:\\\",\\\"x\\\":357,\\\"y\\\":287},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":32,\\\"pos\\\":[{\\\"x\\\":163,\\\"y\\\":332},{\\\"x\\\":958,\\\"y\\\":319},{\\\"x\\\":959,\\\"y\\\":351},{\\\"x\\\":163,\\\"y\\\":364}],\\\"prob\\\":91,\\\"width\\\":796,\\\"word\\\":\\\"1写景的句子侧重于写景手法(感官、角度.动静、虚实、典型画面、寓情于景等)\\\",\\\"x\\\":163,\\\"y\\\":324},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":30,\\\"pos\\\":[{\\\"x\\\":161,\\\"y\\\":380},{\\\"x\\\":768,\\\"y\\\":374},{\\\"x\\\":768,\\\"y\\\":404},{\\\"x\\\":162,\\\"y\\\":410}],\\\"prob\\\":96,\\\"width\\\":607,\\\"word\\\":\\\"②写人的句子侧重于写人手法(动作、心理、肖像、细节等)\\\",\\\"x\\\":161,\\\"y\\\":376},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":30,\\\"pos\\\":[{\\\"x\\\":159,\\\"y\\\":430},{\\\"x\\\":951,\\\"y\\\":417},{\\\"x\\\":951,\\\"y\\\":448},{\\\"x\\\":159,\\\"y\\\":460}],\\\"prob\\\":91,\\\"width\\\":792,\\\"word\\\":\\\"③抒情的句子侧重于抒情方式(直抒胸意、借景抒情、托物言志、用典抒情、\\\",\\\"x\\\":159,\\\"y\\\":423},{\\\"angle\\\":-89,\\\"direction\\\":0,\\\"height\\\":141,\\\"pos\\\":[{\\\"x\\\":155,\\\"y\\\":477},{\\\"x\\\":297,\\\"y\\\":479},{\\\"x\\\":296,\\\"y\\\":507},{\\\"x\\\":155,\\\"y\\\":505}],\\\"prob\\\":96,\\\"width\\\":27,\\\"word\\\":\\\"借古讽今等)\\\",\\\"x\\\":212,\\\"y\\\":420},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":31,\\\"pos\\\":[{\\\"x\\\":154,\\\"y\\\":527},{\\\"x\\\":830,\\\"y\\\":522},{\\\"x\\\":830,\\\"y\\\":553},{\\\"x\\\":154,\\\"y\\\":559}],\\\"prob\\\":97,\\\"width\\\":677,\\\"word\\\":\\\"2.内容:写出…内容,描绘…的情景(画面),体现.特点\\\",\\\"x\\\":154,\\\"y\\\":524},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":30,\\\"pos\\\":[{\\\"x\\\":150,\\\"y\\\":579},{\\\"x\\\":826,\\\"y\\\":571},{\\\"x\\\":827,\\\"y\\\":602},{\\\"x\\\":150,\\\"y\\\":610}],\\\"prob\\\":91,\\\"width\\\":677,\\\"word\\\":\\\"3.情感:表达了……的情感心理),或者渲染了…..的意境氛围\\\",\\\"x\\\":150,\\\"y\\\":575},{\\\"angle\\\":-1,\\\"direction\\\":0,\\\"height\\\":28,\\\"pos\\\":[{\\\"x\\\":148,\\\"y\\\":635},{\\\"x\\\":262,\\\"y\\\":630},{\\\"x\\\":263,\\\"y\\\":658},{\\\"x\\\":149,\\\"y\\\":663}],\\\"prob\\\":97,\\\"width\\\":115,\\\"word\\\":\\\"4.结构:\\\",\\\"x\\\":148,\\\"y\\\":631},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":29,\\\"pos\\\":[{\\\"x\\\":273,\\\"y\\\":631},{\\\"x\\\":916,\\\"y\\\":621},{\\\"x\\\":917,\\\"y\\\":651},{\\\"x\\\":274,\\\"y\\\":661}],\\\"prob\\\":96,\\\"width\\\":643,\\\"word\\\":\\\"照应1与标题或者前后某内容照应),铺垫(为下文作了铺垫)\\\",\\\"x\\\":273,\\\"y\\\":626},{\\\"angle\\\":-90,\\\"direction\\\":0,\\\"height\\\":60,\\\"pos\\\":[{\\\"x\\\":150,\\\"y\\\":712},{\\\"x\\\":210,\\\"y\\\":712},{\\\"x\\\":210,\\\"y\\\":738},{\\\"x\\\":150,\\\"y\\\":738}],\\\"prob\\\":99,\\\"width\\\":26,\\\"word\\\":\\\"说明\\\",\\\"x\\\":167,\\\"y\\\":694},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":31,\\\"pos\\\":[{\\\"x\\\":155,\\\"y\\\":764},{\\\"x\\\":988,\\\"y\\\":752},{\\\"x\\\":989,\\\"y\\\":783},{\\\"x\\\":155,\\\"y\\\":794}],\\\"prob\\\":95,\\\"width\\\":834,\\\"word\\\":\\\"1.所考的是诗歌的第一句,有时要考虑:点明时令,总领全诗,奠定情感基调\\\",\\\"x\\\":154,\\\"y\\\":757},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":31,\\\"pos\\\":[{\\\"x\\\":189,\\\"y\\\":815},{\\\"x\\\":954,\\\"y\\\":809},{\\\"x\\\":954,\\\"y\\\":840},{\\\"x\\\":189,\\\"y\\\":846}],\\\"prob\\\":98,\\\"width\\\":765,\\\"word\\\":\\\"所考的是诗歌的最后一句,有时要考虑:言有尽而意无穷,给读者留下\\\",\\\"x\\\":188,\\\"y\\\":811},{\\\"angle\\\":-89,\\\"direction\\\":0,\\\"height\\\":120,\\\"pos\\\":[{\\\"x\\\":147,\\\"y\\\":874},{\\\"x\\\":267,\\\"y\\\":874},{\\\"x\\\":267,\\\"y\\\":902},{\\\"x\\\":147,\\\"y\\\":902}],\\\"prob\\\":98,\\\"width\\\":28,\\\"word\\\":\\\"想象空间。\\\",\\\"x\\\":191,\\\"y\\\":827},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":32,\\\"pos\\\":[{\\\"x\\\":140,\\\"y\\\":957},{\\\"x\\\":1002,\\\"y\\\":950},{\\\"x\\\":1002,\\\"y\\\":983},{\\\"x\\\":140,\\\"y\\\":990}],\\\"prob\\\":96,\\\"width\\\":862,\\\"word\\\":\\\"2.如果该句没有什么突出手法,那么我们的精力应该花在内容、情感结构上\\\",\\\"x\\\":139,\\\"y\\\":953},{\\\"angle\\\":-89,\\\"direction\\\":0,\\\"height\\\":127,\\\"pos\\\":[{\\\"x\\\":133,\\\"y\\\":1043},{\\\"x\\\":260,\\\"y\\\":1045},{\\\"x\\\":260,\\\"y\\\":1076},{\\\"x\\\":133,\\\"y\\\":1074}],\\\"prob\\\":97,\\\"width\\\":31,\\\"word\\\":\\\"题型迁移\\\",\\\"x\\\":180,\\\"y\\\":995},{\\\"angle\\\":-90,\\\"direction\\\":0,\\\"height\\\":38,\\\"pos\\\":[{\\\"x\\\":5,\\\"y\\\":1109},{\\\"x\\\":44,\\\"y\\\":1109},{\\\"x\\\":44,\\\"y\\\":1150},{\\\"x\\\":5,\\\"y\\\":1150}],\\\"prob\\\":79,\\\"width\\\":40,\\\"word\\\":\\\"二\\\",\\\"x\\\":4,\\\"y\\\":1108},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":34,\\\"pos\\\":[{\\\"x\\\":130,\\\"y\\\":1103},{\\\"x\\\":468,\\\"y\\\":1098},{\\\"x\\\":469,\\\"y\\\":1131},{\\\"x\\\":130,\\\"y\\\":1136}],\\\"prob\\\":97,\\\"width\\\":339,\\\"word\\\":\\\"提问方式:某句诗有什么作用\\\",\\\"x\\\":129,\\\"y\\\":1099},{\\\"angle\\\":-89,\\\"direction\\\":0,\\\"height\\\":411,\\\"pos\\\":[{\\\"x\\\":495,\\\"y\\\":1099},{\\\"x\\\":905,\\\"y\\\":1101},{\\\"x\\\":905,\\\"y\\\":1132},{\\\"x\\\":494,\\\"y\\\":1130}],\\\"prob\\\":97,\\\"width\\\":30,\\\"word\\\":\\\"作用题的答题模式约等于“炼句题”\\\",\\\"x\\\":684,\\\"y\\\":910},{\\\"angle\\\":-1,\\\"direction\\\":0,\\\"height\\\":33,\\\"pos\\\":[{\\\"x\\\":125,\\\"y\\\":1168},{\\\"x\\\":552,\\\"y\\\":1159},{\\\"x\\\":553,\\\"y\\\":1191},{\\\"x\\\":126,\\\"y\\\":1201}],\\\"prob\\\":98,\\\"width\\\":427,\\\"word\\\":\\\"说明:“炼句“与某句诗作用”的区别\\\",\\\"x\\\":124,\\\"y\\\":1163},{\\\"angle\\\":0,\\\"direction\\\":0,\\\"height\\\":33,\\\"pos\\\":[{\\\"x\\\":131,\\\"y\\\":1226},{\\\"x\\\":897,\\\"y\\\":1221},{\\\"x\\\":898,\\\"y\\\":1255},{\\\"x\\\":132,\\\"y\\\":1260}],\\\"prob\\\":95,\\\"width\\\":766,\\\"word\\\":\\\"“炼句”侧重于本句的手法,而“某句诗作用“则是侧重于结构与内容。\\\",\\\"x\\\":130,\\\"y\\\":1224}],\\\"width\\\":1080}\\n\",\"errorExample\":\"\"}]", - "responseParamsDescription": "#### 返回参数说明\n
\n\n|字段|类型|说明|\n|-----|---|--|\n|angle|int|图片的角度(当NeedRotate=true时,返回此字段)。0表示正向,90表示图片朝右,180朝下,270朝左。|\n|content|string|识别出图片的文字块汇总。|\n|prism_wordsInfo|list|文字块信息。|\n|prism_tablesInfo|list|表格信息(当OutputTable=true时,返回此字段)。|\n|prism_wnum|int|识别的文字块的数量,prism_wordsInfo数组的大小。|\n|height|int|算法矫正图片后的高度。|\n|width|int|算法矫正图片后的宽度。|\n|orgHeight|int|原图的高度。|\n|orgWidth|int|原图的宽度。|\n\n#### 文字块信息(prism_wordsInfo字段。)\n|字段|类型|说明|\n|-----|---|--|\n|angle|int|文字块的角度。|\n|height|int|算法矫正图片后的高度。|\n|width|int|算法矫正图片后的宽度。|\n|pos|list|文字块的外矩形四个点的坐标按顺时针排列(左上、右上、右下、左下)。当NeedRotate=true时,如果最外层的angle不为0,需要按照angle矫正图片后,坐标才准确。|\n|word|string|文字块的文字内容。|\n|tableId|int|表格的id(当OutputTable=true时,返回此字段)。|\n|tableCellId|int|表格中单元格的id(当OutputTable=true时,返回此字段)。|\n|charInfo|list|单字信息。|\n\n#### 单字信息(charInfo字段。当OutputCharInfo=true时,返回此字段。)\n|字段|类型|说明|\n|-----|---|--|\n|word|string|单字文字。|\n|prob|int|置信度。|\n|x|int|单字左上角横坐标。|\n|y|int|单字左上角纵坐标。|\n|w|int|单字宽度。|\n|h|int|单字高度。|\n\n#### 表格信息(prism_tablesInfo字段。当OutputTable=true时,返回此字段。)\n|字段|类型|说明|\n|-----|---|--|\n|tableId|int|表格id,和prism_wordsInfo信息中的tableId对应。|\n|xCellSize|int|表格中横坐标单元格的数量。|\n|yCellSize|int|表格中纵坐标单元格的数量。|\n|cellInfos|list|单元格信息。|\n\n#### 单元格信息(cellInfos字段。)\n|字段|类型|说明|\n|-----|---|--|\n|tableCellId|int|表格中单元格id,和prism_wordsInfo信息中的tableCellId对应。|\n|word|string|单元格中的文字。|\n|xsc|int|xStartCell缩写,表示横轴方向该单元格起始在第几个单元格,第一个单元格值为0。|\n|xec|int|xEndCell缩写,表示横轴方向该单元格结束在第几个单元格,第一个单元格值为0,如果xsc和xec都为0说明该文字在横轴方向占据了一个单元格并且在第一个单元格内。|\n|ysc|int|yStartCell缩写,表示纵轴方向该单元格起始在第几个单元格,第一个单元格值为0。|\n|yec|int|yEndCell缩写,表示纵轴方向该单元格结束在第几个单元格,第一个单元格值为0。|\n|pos|list|单元格位置,按照单元格四个角的坐标顺时针排列,分别为左上XY坐标、右上XY坐标、右下XY坐标、左下XY坐标。|", + "produces": [ + "application/octet-stream" + ], + "responseDemo": "[{\"errorExample\":\"\",\"example\":\"\\\"\\\"\",\"type\":\"json\"}]", "schemes": [ "http", "https" @@ -21,125 +25,73 @@ export const routerMeta = { "AK": [] } ], - "summary": "通用手写体识别。", - "title": "通用手写体识别" + "staticInfo": { + "returnType": "synchronous" + }, + "summary": "对目标文件执行SQL语句,返回执行结果。", + "systemTags": { + "operationType": "get" + }, + "title": "对文件执行SQL语句并返回结果" }, "externalDocs": { "description": "去调试", - "url": "https://api.aliyun.com/api/ocr-api/2021-07-07/RecognizeHandwriting" + "url": "https://api.aliyun.com/api/Oss/2019-05-17/SelectObject" }, - "method": "get", - "name": "RecognizeHandwriting", + "method": "post", + "name": "SelectObject", "parameters": [ { - "in": "query", - "name": "Url", - "required": false, + "in": "host", + "name": "bucket", + "required": true, "schema": { - "description": "* 本字段和body字段二选一,不可同时透传或同时为空。\n* 图片链接(长度不超2048,不支持base64)。", - "example": "https://img.alicdn.com/tfs/TB1Wo7eXAvoK1RjSZFDXXXY3pXa-2512-3509.jpg", - "required": false, - "title": "图片链接(长度不超 2048,不支持 base64)", + "description": "Bucket名称。", + "example": "examplebucket", + "required": true, "type": "string" } }, { - "in": "body", - "name": "body", - "required": false, + "in": "path", + "name": "key", + "required": true, "schema": { - "description": "* 本字段和URL字段二选一,不可同时透传或同时为空。\n* 图片二进制文件,最大10MB。\n* 使用HTTP方式调用,把图片二进制文件放到HTTP body中上传即可。\n* 使用SDK的方式调用,把图片放到SDK的body中即可。", - "example": "图片二进制文件", - "format": "binary", - "required": false, - "title": "图片二进制字节流,最大10MB", + "description": "Object的完整路径。", + "example": "exampledir/exampleobject.txt", + "required": true, "type": "string" } }, { - "in": "query", - "name": "OutputCharInfo", - "required": false, - "schema": { - "description": "* 是否输出单字识别结果,默认不需要。\n* true:需要;false:不需要。", - "example": "false", - "required": false, - "title": "是否输出单字识别结果", - "type": "boolean" - } - }, - { - "in": "query", - "name": "NeedRotate", - "required": false, - "schema": { - "description": "* 是否需要自动旋转功能,默认不需要。\n* true:需要;false:不需要。", - "example": "false", - "required": false, - "title": "是否需要自动旋转功能(结构化检测、混贴场景、教育相关场景会自动做旋转,无需设置),返回角度信息", - "type": "boolean" - } - }, - { - "in": "query", - "name": "OutputTable", - "required": false, - "schema": { - "description": "* 是否输出表格识别结果,包含单元格信息,默认不需要。\n* true:需要;false:不需要。", - "example": "false", - "required": false, - "title": "是否输出表格识别结果,包含单元格信息", - "type": "boolean" - } - }, - { - "in": "query", - "name": "NeedSortPage", - "required": false, + "in": "body", + "name": "body", + "required": true, "schema": { - "description": "* 是否按顺序输出文字块,默认为false。\n* false表示从左往右,从上到下的顺序;true表示从上到下,从左往右的顺序。", - "example": "false", - "required": false, - "title": "是否按顺序输出文字块。false表示从左往右,从上到下的顺序;true表示从上到下,从左往右的顺序", - "type": "boolean" + "$ref": "#/definitions/SelectRequest", + "description": "保存SelectObject请求的容器。", + "isDefsType": true, + "required": true, + "typeName": "SelectRequest" } } ], + "path": "/{key}", "responses": { "200": { "schema": { - "description": "Schema of Response", - "properties": { - "Code": { - "description": "状态码", - "example": "200", - "type": "string" - }, - "Data": { - "description": "返回数据", - "example": "{\"content\":\"炼句 提问方式 1.请赏析诗歌某一联(句) 2.赏析某一联(句)的妙处 3.请赏析诗歌某、角度抒胸意、借景抒情、托物\",\"height\":1277,\"orgHeight\":1277,\"orgWidth\":1080,\"prism_version\":\"1.0.9\",\"prism_wnum\":26,\"prism_wordsInfo\":[{\"angle\":-87,\"direction\":0,\"height\":83,\"pos\":[{\"x\":177,\"y\":56},{\"x\":260,\"y\":60},{\"x\":259,\"y\":88},{\"x\":176,\"y\":84}],\"prob\":96,\"width\":28,\"word\":\"炼句\",\"x\":203,\"y\":30}],\"width\":1080}", - "type": "string" - }, - "Message": { - "description": "详细信息 ", - "example": "message", - "type": "string" - }, - "RequestId": { - "description": "请求唯一 ID", - "example": "43A29C77-405E-4CC0-BC55-EE694AD00655", - "type": "string" - } - }, - "title": "Schema of Response", - "type": "object" + "format": "binary", + "type": "string" } - } + }, + "5XX": {} }, - "summary": "通用手写体识别。", - "title": "通用手写体识别" + "summary": "对目标文件执行SQL语句,返回执行结果。", + "title": "对文件执行SQL语句并返回结果" }, - "name": "RecognizeHandwriting", + "name": "SelectObject", "pageType": "document", - "schemaType": "api" + "schemaType": "api", + "code": "// This file is auto-generated, don't edit it. Thanks.\npackage demo;\n\nimport com.aliyun.auth.credentials.Credential;\nimport com.aliyun.auth.credentials.provider.StaticCredentialProvider;\nimport com.aliyun.core.http.HttpClient;\nimport com.aliyun.core.http.HttpMethod;\nimport com.aliyun.core.http.ProxyOptions;\nimport com.aliyun.httpcomponent.httpclient.ApacheAsyncHttpClientBuilder;\nimport com.aliyun.sdk.service.oss20190517.models.*;\nimport com.aliyun.sdk.service.oss20190517.*;\nimport com.google.gson.Gson;\nimport darabonba.core.RequestConfiguration;\nimport darabonba.core.client.ClientOverrideConfiguration;\nimport darabonba.core.utils.CommonUtil;\nimport darabonba.core.TeaPair;\n\n//import javax.net.ssl.KeyManager;\n//import javax.net.ssl.X509TrustManager;\nimport java.net.InetSocketAddress;\nimport java.time.Duration;\nimport java.util.*;\nimport java.util.concurrent.CompletableFuture;\n\npublic class SelectObject {\n public static void main(String[] args) throws Exception {\n\n // HttpClient Configuration\n /*HttpClient httpClient = new ApacheAsyncHttpClientBuilder()\n .connectionTimeout(Duration.ofSeconds(10)) // Set the connection timeout time, the default is 10 seconds\n .responseTimeout(Duration.ofSeconds(10)) // Set the response timeout time, the default is 20 seconds\n .maxConnections(128) // Set the connection pool size\n .maxIdleTimeOut(Duration.ofSeconds(50)) // Set the connection pool timeout, the default is 30 seconds\n // Configure the proxy\n .proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress(\"\", 9001))\n .setCredentials(\"\", \"\"))\n // If it is an https connection, you need to configure the certificate, or ignore the certificate(.ignoreSSL(true))\n .x509TrustManagers(new X509TrustManager[]{})\n .keyManagers(new KeyManager[]{})\n .ignoreSSL(false)\n .build();*/\n\n // Configure Credentials authentication information, including ak, secret, token\n StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()\n // Please ensure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.\n .accessKeyId(System.getenv(\"ALIBABA_CLOUD_ACCESS_KEY_ID\"))\n .accessKeySecret(System.getenv(\"ALIBABA_CLOUD_ACCESS_KEY_SECRET\"))\n //.securityToken(System.getenv(\"ALIBABA_CLOUD_SECURITY_TOKEN\")) // use STS token\n .build());\n\n // Configure the Client\n AsyncClient client = AsyncClient.builder()\n //.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)\n .credentialsProvider(provider)\n //.serviceConfiguration(Configuration.create()) // Service-level configuration\n // Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.\n .overrideConfiguration(\n ClientOverrideConfiguration.create()\n // Endpoint 请参考 https://api.aliyun.com/product/Oss\n .setEndpointOverride(\"oss-cn-qingdao.aliyuncs.com\")\n //.setConnectTimeout(Duration.ofSeconds(30))\n )\n .build();\n\n // Parameter settings for API request\n SelectObjectRequest selectObjectRequest = SelectObjectRequest.builder()\n .selectRequest(selectRequest)\n // Request-level configuration rewrite, can set Http request parameters, etc.\n // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))\n .build();\n\n // Asynchronously get the return value of the API request\n CompletableFuture response = client.selectObject(selectObjectRequest);\n // Synchronously get the return value of the API request\n SelectObjectResponse resp = response.get();\n System.out.println(new Gson().toJson(resp));\n // Asynchronous processing of return values\n /*response.thenAccept(resp -> {\n System.out.println(new Gson().toJson(resp));\n }).exceptionally(throwable -> { // Handling exceptions\n System.out.println(throwable.getMessage());\n return null;\n });*/\n\n // Finally, close the client\n client.close();\n }\n\n}\n", + "language": "java-async" } \ No newline at end of file diff --git a/media/src/pages/_app.tsx b/media/src/pages/_app.tsx index 9179c2e..8c36329 100644 --- a/media/src/pages/_app.tsx +++ b/media/src/pages/_app.tsx @@ -1,6 +1,8 @@ import type { AppProps } from "next/app"; +import "./document/index.module.scss"; import "./document/index.scss"; import "../styles/globals.css"; +import "../main.css" import "@alicloud/console-components/dist/wind.css"; import React from "react"; diff --git a/media/src/pages/document/index.module.scss b/media/src/pages/document/index.module.scss index 26d0cca..8d08317 100644 --- a/media/src/pages/document/index.module.scss +++ b/media/src/pages/document/index.module.scss @@ -1,7 +1,18 @@ +@import "semix-schema-table/module/Markdown.scss"; @import "semix-schema-table/module/SchemaTable.scss"; @import "../../components/SemixFormRender/SemixForm.scss"; @import "../../styles/variable.scss"; @import "../../styles/Markdown.scss"; +@import "../../components/APIPage/API.module.css"; +@import "../../components/APIPage/TryAPI/TryAPI.module.css"; +@import "../../components/APIPage/APIDebugger//widgets/xconsole/enum.module.scss"; +@import "../../components/APIPage/APIDebugger//widgets/xconsole/index.module.scss"; +@import "../../components/APIPage/APIDebugger//widgets/xconsole/list.module.scss"; +@import "../../components/APIPage/APIDebugger/APIGuide.module.scss"; +@import "../../components/APIPage/APIDebugger/APIDebugger.module.scss"; +@import "../../components/APIPage/TrySDK/LanguageSwitcher.module.scss"; +@import "../../components/APIPage/TrySDK/TrySDK.module.scss"; +@import "../../components/common/MonacoEditor.scss"; $primary-color: #448ef7; $nav-height: 36px; @@ -100,19 +111,7 @@ $create-color: #007100; min-width: 100px; } - .api-page-content { - padding: 12px 20px 12px; - display: flex; - .api-debug { - width: 356px; - } - .right-panel { - width: 100%; - } - } - .desc-mod { - background-color: #d6e0e5; border: 1px solid #89a6b5; border-radius: 2px; padding: 8px 18px; diff --git a/media/src/pages/document/index.scss b/media/src/pages/document/index.scss index 5e32002..8d08317 100644 --- a/media/src/pages/document/index.scss +++ b/media/src/pages/document/index.scss @@ -3,6 +3,16 @@ @import "../../components/SemixFormRender/SemixForm.scss"; @import "../../styles/variable.scss"; @import "../../styles/Markdown.scss"; +@import "../../components/APIPage/API.module.css"; +@import "../../components/APIPage/TryAPI/TryAPI.module.css"; +@import "../../components/APIPage/APIDebugger//widgets/xconsole/enum.module.scss"; +@import "../../components/APIPage/APIDebugger//widgets/xconsole/index.module.scss"; +@import "../../components/APIPage/APIDebugger//widgets/xconsole/list.module.scss"; +@import "../../components/APIPage/APIDebugger/APIGuide.module.scss"; +@import "../../components/APIPage/APIDebugger/APIDebugger.module.scss"; +@import "../../components/APIPage/TrySDK/LanguageSwitcher.module.scss"; +@import "../../components/APIPage/TrySDK/TrySDK.module.scss"; +@import "../../components/common/MonacoEditor.scss"; $primary-color: #448ef7; $nav-height: 36px; @@ -101,17 +111,6 @@ $create-color: #007100; min-width: 100px; } - .api-page-content { - padding: 12px 20px 12px; - display: flex; - .api-debug { - width: 356px; - } - .right-panel { - width: 100%; - } - } - .desc-mod { border: 1px solid #89a6b5; border-radius: 2px; diff --git a/media/src/registerService.tsx b/media/src/registerService.tsx index 90186fc..0b2e800 100644 --- a/media/src/registerService.tsx +++ b/media/src/registerService.tsx @@ -5,7 +5,7 @@ import { PontUIService } from "./service/UIService"; if (import.meta.env.PROD) { const requestPostMessage = (message: { type: string; value?: any; requestId:string }): Promise => { // const requestId = _.uniqueId(); - getVSCode().postMessage({ ...message }); + getVSCode()?.postMessage({ ...message }); return new Promise((resove, reject) => { window.addEventListener("message", (event) => { diff --git a/media/src/service/UIService.ts b/media/src/service/UIService.ts index 5f23a8d..62862e3 100644 --- a/media/src/service/UIService.ts +++ b/media/src/service/UIService.ts @@ -1,5 +1,5 @@ import { PontSpec } from "pontx-spec"; -import { ExtensionResponse } from "../types/openAPI"; +import { MakeCodeResponse, OpenAPIResponse } from "../types/openAPI"; /** 不同使用场景,各自注册服务来源 */ const defaultSpecs: any[] = []; @@ -50,6 +50,21 @@ export const PontUIService = { spec: any; }): Promise => {}, - /** 发起调用 */ - openAPIRequest: async (params = {}): Promise => new ExtensionResponse, + /** request openapi */ + openAPIRequest: async (params = {}): Promise => new OpenAPIResponse, + + /** get endpoints list */ + requestEndpoints: async (product: string) => { + return [] as any; + }, + /** get sdk demo */ + makeCodeRequest: async (params = {}): Promise => new MakeCodeResponse, + /** get local language */ + getLocalLanguage : async () => "", + /** update local language */ + updateLocalLanguage : async (language:string) => "", + /** open in ide */ + openInCode: async (codeInfo:{code:string,language:string}): Promise => {}, + /** save to file */ + saveToFile: async (code:string): Promise => {}, }; \ No newline at end of file diff --git a/media/src/types/openAPI.ts b/media/src/types/openAPI.ts index 4f9a498..379972d 100644 --- a/media/src/types/openAPI.ts +++ b/media/src/types/openAPI.ts @@ -51,9 +51,30 @@ export class PontAPI { }; } -export class ExtensionResponse { +export class OpenAPIResponse { requestId : string; doc: string; response: OpenAPIRequestResult; type: string; -} \ No newline at end of file +} + +export class MakeCodeResponse { + code: number; + data: MakeCodeData; +} + +export class MakeCodeData { + demoSdk: any; + apiInfo: APIInfo; + cost: number; +} + +export class APIInfo { + apiStyle: string; + product: string; + method: string; + apiVersion: Date; + apiName: string; + regionId: string; +} + diff --git a/package.json b/package.json index 4c13d18..0339229 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Alibaba Cloud API Toolkit", "description": "The Alibaba Cloud API Toolkit for VSCode makes it easier to access Alibaba Cloud services.", "author": "Alibaba Cloud SDK Team", - "version": "0.0.1", + "version": "0.0.4", "private": true, "publisher": "alibabacloud-openapi", "license": "Apache-2.0", diff --git a/src/Service.ts b/src/Service.ts index 326d0f3..9b8b506 100644 --- a/src/Service.ts +++ b/src/Service.ts @@ -140,6 +140,39 @@ export class AlicloudAPIService { return {}; } + async requestEndpoints(product: string) { + const resStr = await fetch( + `https://pre-api.aliyun.com/meta/v1/products/${product}/endpoints.json?language=zh-CN`, + {}, + ).then((res) => res.text()); + const res = JSON.parse(resStr); + return res?.data?.endpoints || []; + } + + async openInCode(codeInfo:{code:string,language:string}){ + const {language, code} = codeInfo + // 创建新的文件 + vscode.workspace.openTextDocument({ + content: code, + language: language?.toLocaleLowerCase(), + }).then(newDocument => { + vscode.window.showTextDocument(newDocument,{ + viewColumn: vscode.ViewColumn.Beside, + }); + }); + return {} + } + + async saveToFile(code:string){ + const uri = await vscode.window.showSaveDialog(); + if (uri) { + const buf = Buffer.from(code, 'utf8'); + await vscode.workspace.fs.writeFile(uri, buf); + } + return {} + } + + async loadProfiles() { const configFilePath = path.join(os.homedir(), ".aliyun/config.json"); const { R_OK, W_OK } = fs.constants; @@ -153,34 +186,85 @@ export class AlicloudAPIService { } } - async openAPIRequest(requestData) { - const { apiMeta, paramsValue, product, version } = requestData; + async updateLocalLanguage(lang) { + this.context.globalState.update('defaultLanguage', lang); + } + + async getLocalLanguage() { + return this.context.globalState.get('defaultLanguage') + } + + async makeCodeRequest(requestData) { + const { apiMeta, paramsValue, product, version, endpoint, regionId } = requestData; const newParamsValue = getFormatValues(paramsValue, apiMeta?.parameters); - // 定义了一个post变量,用于暂存请求体的信息 - let post = ""; - let response = ""; + const security = apiMeta?.ext?.security; + const defaultCredentialType = + security?.length > 0 + ? security.indexOf("AK") < 0 + ? security.indexOf("BearerToken") < 0 + ? "anonymous" + : "bearer" + : "ak" + : "ak"; + const body = { + "apiName": apiMeta?.name, + "apiVersion": version, + "product": product, + "sdkType": "dara", + "params": newParamsValue || {}, + "regionId": regionId, + "endpoint": endpoint, + "credential": {type: defaultCredentialType}, + "runtimeOptions": {}, + "useCommon": false + } + const resStr = await fetch( + `https://api.aliyun.com/api/product/makeCode`, + {method: 'post', + body: JSON.stringify(body), + headers: {'Content-Type': 'application/json'}}, + ).then((res) => res.text()); + const res = JSON.parse(resStr); + return res; + } + + async openAPIRequest(requestData) { + const { apiMeta, paramsValue, product, version, endpoint } = requestData; + // const newParamsValue = getFormatValues(paramsValue, apiMeta?.parameters); + let response = {} as any; let data; const profilesInfo = await this.loadProfiles(); const profiles = profilesInfo?.profiles; // TODO:用户可以选择使用哪个profile + const security = apiMeta?.ext?.security; + const defaultCredentialType = + security?.length > 0 + ? security.indexOf("AK") < 0 + ? security.indexOf("BearerToken") < 0 + ? "anonymous" + : "bearer" + : "ak" + : "ak"; if (profiles?.length) { + const profile = profiles?.find(item=>item.name === profilesInfo.current) + const start = Date.now(); try { data = await request({ - accessKeyId: profiles[0]?.access_key_id, - accessKeySecret: profiles[0]?.access_key_secret, - // TODO:可选服务地址 - endpoint: "ecs-cn-hangzhou.aliyuncs.com", + accessKeyId: profile?.access_key_id, + accessKeySecret: profile?.access_key_secret, + endpoint: endpoint, action: apiMeta?.name, apiVersion: version, - params: newParamsValue || {}, + params: paramsValue || {}, productName: product, - meta: this.pontManager.localPontSpecs[0], + meta: apiMeta, bodyStyle: undefined, - credential: "AK", + credential: {type: defaultCredentialType}, }); response = data; // 设置状态码 // res.writeHead(200); + response.cost = Date.now() - start; } catch (error) { console.log("response error:", error); if (error && error.name === "RequesctTimeoutError") { @@ -201,12 +285,14 @@ export class AlicloudAPIService { message: error.message, notice: "The request has executed failed.", }, + cost: 300, entry: error.entry || { url: "", }, }; } response = data; + response.cost = Date.now() - start; // 设置状态码 // res.writeHead(500); } @@ -215,14 +301,13 @@ export class AlicloudAPIService { requestId: requestData.requestId, doc: `${product}::${version}::${apiMeta.name}`, type: "openAPIResponse", - response, + response }; }else{ - let result = await vscode.window.showErrorMessage("请先安装阿里云 CLI 插件,并完成AK/SK配置后,再发起调用", "install","cancel"); - if (result === "install") { - vscode.env.openExternal(vscode.Uri.parse('vscode:extension/alibabacloud-openapi.aliyuncli')); + let result = await vscode.window.showErrorMessage("请完成AK/SK配置后,再发起调用", "查看配置方法","取消"); + if (result === "查看配置方法") { + vscode.env.openExternal(vscode.Uri.parse('https://github.com/aliyun/aliyun-cli?tab=readme-ov-file#configure')); } - } } diff --git a/src/extension.ts b/src/extension.ts index f916212..e32737f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -54,7 +54,7 @@ export async function activate(context: vscode.ExtensionContext) { ); if (pontManager) { - console.log('Congratulations, your extension "Alibaba Cloud API Toolkit" is now active!!!!'); + console.log('Congratulations, your extension "Alibaba Cloud API Toolkit" is now active!'); alicloudAPIMessageService.startup(pontManager, context); context.subscriptions.push( vscode.window.registerWebviewPanelSerializer(AlicloudAPIWebview.viewType, new AlicloudAPISerializer()), diff --git a/src/openApiService/request/request.ts b/src/openApiService/request/request.ts index 3133f76..5b98adf 100644 --- a/src/openApiService/request/request.ts +++ b/src/openApiService/request/request.ts @@ -98,20 +98,28 @@ export const request = async function (options: OpenAPIOptions) { bodyStyle, credential } = options; - let method = meta?.apis[action]?.method?.toUpperCase(); + let method = meta?.method?.toUpperCase(); let protocol = 'https'; endpoint = endpoint ? endpoint.replace('http://', '').replace('https://', '') : `${productName.toLowerCase()}.cn-hangzhou.aliyuncs.com`; let pathname = '/'; - const schema = meta.apis[action].responses['200'] && meta.apis[action].responses['200'].schema; - const requestType = bodyStyle === 'json' ? 'json' : 'formData'; + const schema = meta?.responses['200'] && meta?.responses['200'].schema; + let requestType; + if(meta?.consumes){ + requestType = _bodyType(meta?.consumes) + }else{ + requestType = bodyStyle === 'json' ? 'json' : 'formData'; + } let responseType; + if (!schema) { responseType = _bodyType(meta.apis[action] && meta.apis[action].produces); } else if (schema.xml) { responseType = 'xml'; } else if (schema.type && schema.type !== 'object') { responseType = schema.format || schema.type; - } else { + } else if (meta?.ext?.produces){ + responseType = _bodyType(meta.ext.produces); + }else { responseType = 'json'; } @@ -128,7 +136,7 @@ export const request = async function (options: OpenAPIOptions) { // }); // paramObject.params = newParams; const parameters = {}; - meta.apis[action]?.parameters?.map(param=>{ + meta?.parameters?.map(param=>{ parameters[param.name] = param; }) // paramObject.params = params; @@ -177,7 +185,8 @@ export const request = async function (options: OpenAPIOptions) { } request.query[name] = value; break; - case 'Body': + case 'body': + case 'formData': if (!request.body) { request.body = {}; } @@ -193,7 +202,7 @@ export const request = async function (options: OpenAPIOptions) { // request.stream = await ossUtil.getStream(`tmpFile/${params[name]}`); } break; - case 'Header': + case 'header': request.headers[name] = value; break; } @@ -224,7 +233,6 @@ export const request = async function (options: OpenAPIOptions) { readTimeout: 50000, connectTimeout: 50000 }); - request.query = {}; const data = { version: apiVersion, method, @@ -232,9 +240,7 @@ export const request = async function (options: OpenAPIOptions) { action, reqBodyType: requestType, bodyType: responseType, - // TODO:根据元数据判断鉴权方式 - authType:'AK', - // authType: credential && credential.type === 'anonymous' ? 'Anonymous' : 'AK' + authType: 'AK', }; return await client.doRequest(data, request, {}); }; \ No newline at end of file diff --git a/src/webview.ts b/src/webview.ts index f3b373b..f4bb43a 100644 --- a/src/webview.ts +++ b/src/webview.ts @@ -63,6 +63,7 @@ export class AlicloudAPIWebview { { // Enable javascript in the webview enableScripts: true, + retainContextWhenHidden: true }, ); webview = AlicloudAPIWebview.webviewPanels[panelKey]; @@ -112,6 +113,7 @@ export class AlicloudAPIWebview { { // Enable javascript in the webview enableScripts: true, + retainContextWhenHidden: true }, ); const filewatcher = vscode.workspace.createFileSystemWatcher(filePath, true, false, true);