This is an automated email from the ASF dual-hosted git repository.
benjobs pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampark.git
The following commit(s) were added to refs/heads/dev by this push:
new c7b6b4136 [Improve]: add openapi schema modal (#3915)
c7b6b4136 is described below
commit c7b6b41360f6f2795d369181038ed9d0db7fda7c
Author: Kriszu <[email protected]>
AuthorDate: Fri Jul 26 00:16:41 2024 +0800
[Improve]: add openapi schema modal (#3915)
* [Improve]: add openapi schema modal
* [Improve]: modal title
* [Fix]: api method style
* [Fix]: License header
---------
Co-authored-by: benjobs <[email protected]>
---
.../streampark-console-webapp/.npmrc | 16 ++
.../src/api/flink/savepoint.ts | 2 +-
.../src/api/system/openapi.ts | 4 +-
.../src/assets/icons/api.svg | 1 +
.../src/components/OpenApi/index.ts | 5 +
.../src/components/OpenApi/src/index.tsx | 211 +++++++++++++++++++++
.../src/design/ant/index.less | 2 +-
.../src/locales/lang/en/component.ts | 8 +
.../src/locales/lang/en/flink/app.ts | 2 +
.../src/locales/lang/zh-CN/component.ts | 8 +
.../src/locales/lang/zh-CN/flink/app.ts | 2 +
.../src/views/flink/app/Detail.vue | 71 +++----
.../flink/app/components/AppDetail/DetailTab.vue | 4 +-
.../flink/app/components/RequestModal/index.tsx | 100 ++++++++++
.../src/views/flink/app/hooks/useApp.tsx | 4 +-
15 files changed, 383 insertions(+), 57 deletions(-)
diff --git a/streampark-console/streampark-console-webapp/.npmrc
b/streampark-console/streampark-console-webapp/.npmrc
new file mode 100644
index 000000000..27dc87179
--- /dev/null
+++ b/streampark-console/streampark-console-webapp/.npmrc
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package-manager-strict=false
diff --git
a/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts
b/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts
index b4964f6e3..4f66cfc94 100644
--- a/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts
+++ b/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts
@@ -26,7 +26,7 @@ enum SAVE_POINT_API {
export function fetchLatest(data: Recordable) {
return defHttp.post({ url: SAVE_POINT_API.LATEST, data });
}
-export function fetchSavePonitHistory(data: Recordable) {
+export function fetchSavePointHistory(data: Recordable) {
return defHttp.post({ url: SAVE_POINT_API.HISTORY, data });
}
/**
diff --git
a/streampark-console/streampark-console-webapp/src/api/system/openapi.ts
b/streampark-console/streampark-console-webapp/src/api/system/openapi.ts
index 826c71e8f..c42454566 100644
--- a/streampark-console/streampark-console-webapp/src/api/system/openapi.ts
+++ b/streampark-console/streampark-console-webapp/src/api/system/openapi.ts
@@ -26,8 +26,8 @@ enum Api {
* @param data
* @returns {Promise<number>}
*/
-export function fetchApiSchema(data) {
- return defHttp.post<number>({ url: Api.SCHEMA, data });
+export function fetchApiSchema(data: { name: string }) {
+ return defHttp.post({ url: Api.SCHEMA, data });
}
/**
* copyCurl
diff --git
a/streampark-console/streampark-console-webapp/src/assets/icons/api.svg
b/streampark-console/streampark-console-webapp/src/assets/icons/api.svg
new file mode 100644
index 000000000..a7d1ff984
--- /dev/null
+++ b/streampark-console/streampark-console-webapp/src/assets/icons/api.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG
1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg
t="1721919310491" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="12755"
xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path
d="M409.6 64l-0.064 128H505.6V64h76.8v128h96V64h76.8v128H896v140.736l128
0.064v76.8l-128-0.064v96l128 0.064v76.8l-128-0.064v96l128
0.064v76.8l-128-0.064V896h-140 [...]
\ No newline at end of file
diff --git
a/streampark-console/streampark-console-webapp/src/components/OpenApi/index.ts
b/streampark-console/streampark-console-webapp/src/components/OpenApi/index.ts
new file mode 100644
index 000000000..135f27faf
--- /dev/null
+++
b/streampark-console/streampark-console-webapp/src/components/OpenApi/index.ts
@@ -0,0 +1,5 @@
+import { withInstall } from '/@/utils';
+
+import openApi from './src';
+
+export const OpenApi = withInstall(openApi);
diff --git
a/streampark-console/streampark-console-webapp/src/components/OpenApi/src/index.tsx
b/streampark-console/streampark-console-webapp/src/components/OpenApi/src/index.tsx
new file mode 100644
index 000000000..6f35837f6
--- /dev/null
+++
b/streampark-console/streampark-console-webapp/src/components/OpenApi/src/index.tsx
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Divider, Table, Tag, type TableColumnType, Empty, Skeleton } from
'ant-design-vue';
+import { defineComponent, ref, shallowRef, watchEffect } from 'vue';
+import { fetchApiSchema } from '/@/api/system/openapi';
+import { baseUrl } from '/@/api';
+import { useAppStore } from '/@/store/modules/app';
+import { ThemeEnum } from '/@/enums/appEnum';
+import { useI18n } from '/@/hooks/web/useI18n';
+interface RequestSchemas {
+ url: string;
+ method?: string;
+ params?: Recordable[];
+ body?: Recordable[];
+ header?: Recordable[];
+}
+
+const methodMap = {
+ GET: {
+ lightColor: '#22c55e',
+ darkColor: '#10b981',
+ },
+ POST: {
+ lightColor: '#f59e0b',
+ darkColor: '#eab308',
+ },
+ PUT: {
+ lightColor: '#3b82f6',
+ darkColor: '#0ea5e9 ',
+ },
+ DELETE: {
+ lightColor: '#ef4444',
+ darkColor: '#f43f5e',
+ },
+ PATCH: {
+ lightColor: '#a855f7',
+ darkColor: '#8b5cf6',
+ },
+ DEFAULT: {
+ lightColor: '#737373',
+ darkColor: '#71717a',
+ },
+} as const;
+export default defineComponent({
+ name: 'OpenApi',
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ },
+ setup(props) {
+ const requestRef = shallowRef<RequestSchemas>({
+ url: '',
+ });
+ const { t } = useI18n();
+ const fetchLoading = ref(false);
+ const appStore = useAppStore();
+ const handleGetRequestSchemas = async () => {
+ try {
+ fetchLoading.value = true;
+ const resp = await fetchApiSchema({
+ name: props.name,
+ });
+ requestRef.value = {
+ url: baseUrl() + resp.url,
+ method: resp.method,
+ params: resp.schema,
+ body: resp.body,
+ header: resp.header,
+ };
+ } catch (error) {
+ console.error(error);
+ } finally {
+ fetchLoading.value = false;
+ }
+ };
+ const tableColumns = shallowRef<TableColumnType[]>([
+ { title: t('component.openApi.param'), dataIndex: 'name', width: 160 },
+ { title: t('component.openApi.defaultValue'), dataIndex: 'defaultValue',
width: 130 },
+ { title: t('component.openApi.type'), dataIndex: 'type', width: 150 },
+ {
+ title: t('component.openApi.required'),
+ dataIndex: 'required',
+ customRender: ({ text }) => (
+ <Tag color={text ? 'success' : 'error'}>{text ? t('common.yes') :
t('common.no')}</Tag>
+ ),
+ },
+ { title: t('component.openApi.description'), dataIndex: 'description' },
+ ]);
+
+ watchEffect(() => {
+ if (props.name) {
+ handleGetRequestSchemas();
+ }
+ });
+
+ const renderParams = () => {
+ if (!requestRef.value.params) return null;
+ return (
+ <>
+ <Divider orientation="left">Params</Divider>
+ {renderTableData(requestRef.value.params)}
+ </>
+ );
+ };
+
+ const renderBody = () => {
+ if (!requestRef.value.body) return null;
+ return (
+ <>
+ <Divider orientation="left">Body</Divider>
+ {renderTableData(requestRef.value.body)}
+ </>
+ );
+ };
+ const renderHeader = () => {
+ if (!requestRef.value.header) return null;
+ return (
+ <>
+ <Divider orientation="left">Header</Divider>
+ {renderTableData(requestRef.value.header)}
+ </>
+ );
+ };
+ const renderTableData = (data: Recordable[]) => {
+ if (!data || (Array.isArray(data) && data.length === 0))
+ return (
+ <>
+ <Empty
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
+ v-slots={{
+ description: () => <span
class="text-gray-4">{t('component.openApi.empty')}</span>,
+ }}
+ ></Empty>
+ </>
+ );
+ return (
+ <>
+ <Table
+ size="small"
+ bordered
+ pagination={false}
+ dataSource={data}
+ columns={tableColumns.value}
+ ></Table>
+ </>
+ );
+ };
+ const renderRequestMethod = () => {
+ if (!requestRef.value.method) return null;
+ const currentMethod =
+ methodMap[requestRef.value.method.toLocaleUpperCase()] ??
methodMap.DEFAULT;
+ const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
+ return (
+ <div class="relative flex">
+ <label for="method">
+ <span class="flex overflow-hidden text-ellipsis whitespace-nowrap">
+ <div class="flex flex-1 relative">
+ <div
+ id="method"
+ class="flex w-20 rounded-l bg-[#f9fafb] dark:bg-[#1c1c1e]
px-4 py-2 font-semibold justify-center transition"
+ style={{
+ color: darkMode ? currentMethod.lightColor :
currentMethod.darkColor,
+ }}
+ >
+ {requestRef.value.method.toLocaleUpperCase()}
+ </div>
+ </div>
+ </span>
+ </label>
+ </div>
+ );
+ };
+
+ return () => (
+ <>
+ <Skeleton loading={fetchLoading.value} active>
+ <div class="flex-none flex-shrink-0 ">
+ <div class="min-w-[12rem] flex min-h-9 flex-1 whitespace-nowrap
rounded border dark:border-[#1f1f1f] border-[#f3f4f6]">
+ {renderRequestMethod()}
+ <div
+ class="flex flex-1 items-center text-[#111827]
whitespace-nowrap rounded-r border-l border-[#f3f4f6] bg-[#f9fafb]
dark:bg-[#1c1c1e] dark:border-[#1f1f1f] transition "
+ style="padding-left:10px"
+ >
+ {requestRef.value.url}
+ </div>
+ </div>
+ </div>
+ {renderHeader()}
+ {renderParams()}
+ {renderBody()}
+ </Skeleton>
+ </>
+ );
+ },
+});
diff --git
a/streampark-console/streampark-console-webapp/src/design/ant/index.less
b/streampark-console/streampark-console-webapp/src/design/ant/index.less
index 5d4f5ce84..a128f696b 100644
--- a/streampark-console/streampark-console-webapp/src/design/ant/index.less
+++ b/streampark-console/streampark-console-webapp/src/design/ant/index.less
@@ -77,7 +77,7 @@ span.anticon:not(.app-iconify) {
}
.app-bar,
-.streampark-basic-title {
+div:not(.ant-modal-title)>.streampark-basic-title {
background-color: @background-color-base;
height: 100%;
font-size: 14px !important;
diff --git
a/streampark-console/streampark-console-webapp/src/locales/lang/en/component.ts
b/streampark-console/streampark-console-webapp/src/locales/lang/en/component.ts
index 2a33235c3..810cfcfb8 100644
---
a/streampark-console/streampark-console-webapp/src/locales/lang/en/component.ts
+++
b/streampark-console/streampark-console-webapp/src/locales/lang/en/component.ts
@@ -120,4 +120,12 @@ export default {
dragText: 'Hold down the slider and drag',
successText: 'Verified',
},
+ openApi: {
+ param: 'Parameter Name',
+ defaultValue: 'Default Value',
+ type: 'Type',
+ required: 'Required',
+ description: 'Description',
+ empty: 'This request has no data of this type',
+ },
};
diff --git
a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
index 1fad1b3c7..e9f14bf18 100644
---
a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
+++
b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
@@ -119,6 +119,8 @@ export default {
compare: 'Compare',
compareSelectTips: 'Please select the target version',
resetApi: 'Rest Api',
+ copyCurl: 'Copy Curl',
+ apiTitle: 'Api Detail',
resetApiToolTip:
'Rest API external call interface,other third-party systems easy to
access StreamPark',
copyStartcURL: 'App Start',
diff --git
a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/component.ts
b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/component.ts
index e785b88ad..6861f7c38 100644
---
a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/component.ts
+++
b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/component.ts
@@ -125,4 +125,12 @@ export default {
dragText: '请按住滑块拖动',
successText: '验证通过',
},
+ openApi: {
+ param: '参数名',
+ defaultValue: '默认值',
+ required: '必填',
+ type: '类型',
+ description: '说明',
+ empty: '该请求暂无该类型数据',
+ },
};
diff --git
a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
index 4c6d070cd..8ecaff1d0 100644
---
a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
+++
b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
@@ -110,6 +110,8 @@ export default {
compare: '比较',
compareSelectTips: '请选择目标板本',
resetApi: 'Open API',
+ copyCurl: '复制 CURL',
+ apiTitle: 'Api 详情',
resetApiToolTip: 'OPEN API,第三方系统可轻松对接 StreamPark',
copyStartcURL: '作业启动',
copyCancelcURL: '作业停止',
diff --git
a/streampark-console/streampark-console-webapp/src/views/flink/app/Detail.vue
b/streampark-console/streampark-console-webapp/src/views/flink/app/Detail.vue
index cd38d9148..f5e8a67cb 100644
---
a/streampark-console/streampark-console-webapp/src/views/flink/app/Detail.vue
+++
b/streampark-console/streampark-console-webapp/src/views/flink/app/Detail.vue
@@ -14,48 +14,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<script lang="ts">
- import { defineComponent } from 'vue';
+<script setup lang="ts" name="ApplicationDetail">
import { AppStateEnum, ExecModeEnum } from '/@/enums/flinkEnum';
import { useI18n } from '/@/hooks/web/useI18n';
import { fetchAppExternalLink } from '/@/api/setting/externalLink';
import { ExternalLink } from '/@/api/setting/types/externalLink.type';
- export default defineComponent({
- name: 'ApplicationDetail',
- });
-</script>
-<script setup lang="ts" name="ApplicationDetail">
+ import { useModal } from '/@/components/Modal';
import { PageWrapper } from '/@/components/Page';
import { Description, useDescription } from '/@/components/Description';
import { Icon } from '/@/components/Icon';
import { useRoute, useRouter } from 'vue-router';
import { fetchBackUps, fetchGet, fetchOptionLog, fetchYarn } from
'/@/api/flink/app';
import { onUnmounted, reactive, h, unref, ref, onMounted, computed } from
'vue';
- import { useIntervalFn, useClipboard } from '@vueuse/core';
+ import { useIntervalFn } from '@vueuse/core';
import { AppListRecord } from '/@/api/flink/app.type';
import { Tooltip, Divider, Space } from 'ant-design-vue';
import { handleView } from './utils';
import { Button } from '/@/components/Button';
import { getDescSchema } from './data/detail.data';
- import { fetchCheckToken } from '/@/api/system/token';
- import { fetchCopyCurl } from '/@/api/system/openapi';
- import { useMessage } from '/@/hooks/web/useMessage';
- import { baseUrl } from '/@/api';
import { fetchListVer } from '/@/api/flink/config';
- import { fetchSavePonitHistory } from '/@/api/flink/savepoint';
+ import { fetchSavePointHistory } from '/@/api/flink/savepoint';
import Mergely from './components/Mergely.vue';
import DetailTab from './components/AppDetail/DetailTab.vue';
+ import RequestModal from './components/RequestModal';
import { createDetailProviderContext } from './hooks/useDetailContext';
import { useDrawer } from '/@/components/Drawer';
import { LinkBadge } from '/@/components/LinkBadge';
+ defineOptions({
+ name: 'ApplicationDetail',
+ });
const route = useRoute();
const router = useRouter();
- const { Swal, createMessage } = useMessage();
- const { copy } = useClipboard({
- legacy: true,
- });
const { t } = useI18n();
const yarn = ref('');
@@ -89,7 +80,11 @@
type: 'primary',
size: 'small',
class: 'mx-3px px-5px',
- onClick: () => handleCopyCurl('flinkStart'),
+ onClick: () =>
+ openApiModal(true, {
+ name: 'flinkStart',
+ app,
+ }),
},
() => [t('flink.app.detail.copyStartcURL')],
),
@@ -99,7 +94,12 @@
type: 'primary',
size: 'small',
class: 'mx-3px px-5px',
- onClick: () => handleCopyCurl('flinkCancel'),
+ onClick: () => {
+ openApiModal(true, {
+ name: 'flinkCancel',
+ app,
+ });
+ },
},
() => [t('flink.app.detail.copyCancelcURL')],
),
@@ -112,6 +112,7 @@
});
const [registerConfDrawer] = useDrawer();
+ const [registerOpenApi, { openModal: openApiModal }] = useModal();
/* Flink Web UI */
function handleFlinkView() {
@@ -155,7 +156,7 @@
};
const confList = await fetchListVer(commonParams);
- const pointHistory = await fetchSavePonitHistory(commonParams);
+ const pointHistory = await fetchSavePointHistory(commonParams);
const backupList = await fetchBackUps(commonParams);
const optionList = await fetchOptionLog(commonParams);
@@ -170,35 +171,6 @@
yarn.value = await fetchYarn();
}
- /* copyCurl */
- async function handleCopyCurl(name) {
- const resp = await fetchCheckToken({});
- const result = parseInt(resp);
- if (result === 0) {
- Swal.fire({
- icon: 'error',
- title: t('flink.app.detail.nullAccessToken'),
- showConfirmButton: true,
- timer: 3500,
- });
- } else if (result === 1) {
- Swal.fire({
- icon: 'error',
- title: t('flink.app.detail.invalidAccessToken'),
- showConfirmButton: true,
- timer: 3500,
- });
- } else {
- const res = await fetchCopyCurl({
- baseUrl: baseUrl(),
- appId: app.id,
- name: name,
- });
- copy(res);
- createMessage.success(t('flink.app.detail.detailTab.copySuccess'));
- }
- }
-
async function getExternalLinks() {
const { data: links } = await fetchAppExternalLink({ appId:
route.query.appId as string });
externalLinks.value = links.data;
@@ -248,6 +220,7 @@
<Divider class="mt-20px -mb-17px" />
<DetailTab :app="app" :tabConf="detailTabs" />
<Mergely @register="registerConfDrawer" :readOnly="true" />
+ <RequestModal @register="registerOpenApi" />
</PageWrapper>
</template>
<style lang="less">
diff --git
a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue
b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue
index 038d2e688..0d3300c6a 100644
---
a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue
+++
b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue
@@ -39,7 +39,7 @@
import { getMonacoOptions } from '../../data';
import { useRoute } from 'vue-router';
import { fetchGetVer, fetchListVer, fetchRemoveConf } from
'/@/api/flink/config';
- import { fetchRemoveSavePoint, fetchSavePonitHistory } from
'/@/api/flink/savepoint';
+ import { fetchRemoveSavePoint, fetchSavePointHistory } from
'/@/api/flink/savepoint';
import {
fetchBackUps,
@@ -136,7 +136,7 @@
);
const [registerSavePointTable, { reload: reloadSavePoint }] = useTable({
- api: fetchSavePonitHistory,
+ api: fetchSavePointHistory,
columns: getSavePointColumns(),
...tableCommonConf,
});
diff --git
a/streampark-console/streampark-console-webapp/src/views/flink/app/components/RequestModal/index.tsx
b/streampark-console/streampark-console-webapp/src/views/flink/app/components/RequestModal/index.tsx
new file mode 100644
index 000000000..a065b773f
--- /dev/null
+++
b/streampark-console/streampark-console-webapp/src/views/flink/app/components/RequestModal/index.tsx
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { defineComponent, ref } from 'vue';
+import { BasicModal, useModalInner } from '/@/components/Modal';
+import { OpenApi } from '/@/components/OpenApi';
+import { fetchCheckToken } from '/@/api/system/token';
+import { useMessage } from '/@/hooks/web/useMessage';
+import { useI18n } from '/@/hooks/web/useI18n';
+import { fetchCopyCurl } from '/@/api/system/openapi';
+import { baseUrl } from '/@/api';
+import { useClipboard } from '@vueuse/core';
+import { SvgIcon } from '/@/components/Icon';
+
+export default defineComponent({
+ name: 'RequestModal',
+ emits: ['register'],
+ setup() {
+ const currentRef = ref<Recordable>({});
+ const [registerModal, { closeModal, changeOkLoading }] =
useModalInner(async (data) => {
+ currentRef.value = data;
+ });
+ const { Swal, createMessage } = useMessage();
+ const { copy } = useClipboard({
+ legacy: true,
+ });
+ const { t } = useI18n();
+ const handleCopyCurl = async () => {
+ try {
+ changeOkLoading(true);
+ const resp = await fetchCheckToken({});
+ const result = parseInt(resp);
+ if (result === 0) {
+ Swal.fire({
+ icon: 'error',
+ title: t('flink.app.detail.nullAccessToken'),
+ showConfirmButton: true,
+ timer: 3500,
+ });
+ } else if (result === 1) {
+ Swal.fire({
+ icon: 'error',
+ title: t('flink.app.detail.invalidAccessToken'),
+ showConfirmButton: true,
+ timer: 3500,
+ });
+ } else {
+ const res = await fetchCopyCurl({
+ baseUrl: baseUrl(),
+ appId: currentRef.value.app.id,
+ name: currentRef.value.name,
+ });
+ copy(res);
+ createMessage.success(t('flink.app.detail.detailTab.copySuccess'));
+ closeModal();
+ }
+ } catch (error) {
+ console.log(error);
+ } finally {
+ changeOkLoading(false);
+ }
+ };
+ return () => (
+ <>
+ <BasicModal
+ width={900}
+ onRegister={registerModal}
+ minHeight={400}
+ okText={t('flink.app.detail.copyCurl')}
+ onOk={handleCopyCurl}
+ v-slots={{
+ title: () => (
+ <>
+ <div class="flex items-center">
+ <SvgIcon name="api" size={24}></SvgIcon>
+ <div class="pl-6px">{t('flink.app.detail.apiTitle')}</div>
+ </div>
+ </>
+ ),
+ }}
+ >
+ {currentRef.value.name && <OpenApi
name={currentRef.value.name}></OpenApi>}
+ </BasicModal>
+ </>
+ );
+ },
+});
diff --git
a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
index d7fec2f60..22257b8a5 100644
---
a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
+++
b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
@@ -19,7 +19,7 @@ import { h, onMounted, reactive, ref, unref, VNode } from
'vue';
import { handleAppBuildStatueText } from '../utils';
import { fetchCheckName, fetchCopy, fetchAbort, fetchMapping } from
'/@/api/flink/app';
import { fetchBuild, fetchBuildDetail } from '/@/api/flink/flinkBuild';
-import { fetchSavePonitHistory } from '/@/api/flink/savepoint';
+import { fetchSavePointHistory } from '/@/api/flink/savepoint';
import { fetchAppOwners } from '/@/api/system/user';
import { SvgIcon } from '/@/components/Icon';
import { AppStateEnum, ExecModeEnum, OptionStateEnum } from
'/@/enums/flinkEnum';
@@ -122,7 +122,7 @@ export const useFlinkApplication = (openStartModal: Fn) => {
Swal.fire('Failed', 'please set flink version first.', 'error');
} else {
if (!optionApps.starting.get(app.id) || app['optionState'] ===
OptionStateEnum.NONE) {
- const resp = await fetchSavePonitHistory({
+ const resp = await fetchSavePointHistory({
appId: app.id,
pageNum: 1,
pageSize: 9999,