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 60fcbc788 [Feature] add depend apps page and fix alert setting style
(#1921)
60fcbc788 is described below
commit 60fcbc7886e9c54928e25a197bae88e17d23d565
Author: Sizhu Wang <[email protected]>
AuthorDate: Fri Oct 28 23:21:39 2022 +0800
[Feature] add depend apps page and fix alert setting style (#1921)
---
.../src/api/flink/setting/types/alert.type.ts | 1 +
.../src/api/system/variable.ts | 11 +
.../src/components/CardList/src/CardList.vue | 4 +-
.../src/design/public.less | 22 +-
.../src/layouts/default/footer/index.vue | 6 +-
.../src/router/constant.ts | 3 +
.../src/router/guard/permissionGuard.ts | 1 -
.../src/settings/projectSetting.ts | 2 +-
.../src/store/modules/permission.ts | 6 +-
.../src/store/modules/user.ts | 12 +-
.../src/utils/auth/index.ts | 29 ++-
.../src/utils/cache/persistent.ts | 11 -
.../src/views/base/login/Login.vue | 222 +++++++++++----------
.../src/views/base/login/LoginForm.vue | 7 +-
.../src/views/flink/app/EditStreamPark.vue | 40 +++-
.../src/views/flink/app/data/index.ts | 2 +-
.../src/views/flink/setting/View.less | 2 +-
.../src/views/flink/setting/View.vue | 6 +-
.../views/flink/setting/components/AlertModal.vue | 208 ++++++-------------
.../flink/setting/components/AlertSetting.vue | 203 ++++++++++++-------
.../flink/setting/components/AlertTypeInfo.vue | 119 +++++++++++
.../views/flink/setting/components/SettingList.vue | 1 +
.../flink/setting/components/SystemSetting.vue | 17 +-
.../views/flink/setting/components/alert.data.ts | 79 ++++++--
.../views/flink/setting/hooks/useClusterSetting.ts | 8 +-
.../src/views/system/variable/DependApps.vue | 70 +++++++
.../src/views/system/variable/View.vue | 27 ++-
.../variable/{ => components}/VariableDrawer.vue | 1 -
.../variable/{ => components}/VariableInfo.vue | 0
29 files changed, 701 insertions(+), 419 deletions(-)
diff --git
a/streampark-console/streampark-console-newui/src/api/flink/setting/types/alert.type.ts
b/streampark-console/streampark-console-newui/src/api/flink/setting/types/alert.type.ts
index 6af8c3e22..9606523c0 100644
---
a/streampark-console/streampark-console-newui/src/api/flink/setting/types/alert.type.ts
+++
b/streampark-console/streampark-console-newui/src/api/flink/setting/types/alert.type.ts
@@ -26,6 +26,7 @@ export interface AlertSetting {
larkParams: string;
createTime: string;
modifyTime: string;
+ alertTypeTags?: string[];
}
// Create an alert
diff --git
a/streampark-console/streampark-console-newui/src/api/system/variable.ts
b/streampark-console/streampark-console-newui/src/api/system/variable.ts
index 7ba3b1a61..25e247f4e 100644
--- a/streampark-console/streampark-console-newui/src/api/system/variable.ts
+++ b/streampark-console/streampark-console-newui/src/api/system/variable.ts
@@ -22,6 +22,7 @@ import { VariableDeleteParam, VariableListRecord,
VariableParam } from './model/
enum VARIABLE_API {
LIST = '/variable/list',
+ DEPEND = '/variable/dependApps',
UPDATE = '/variable/update',
POST = '/variable/post',
DELETE = '/variable/delete',
@@ -62,6 +63,7 @@ export function fetchUpdateVariable(data: VariableParam):
Promise<boolean | unde
export function fetchVariableDelete(data: VariableDeleteParam):
Promise<AxiosResponse<Result>> {
return defHttp.delete({ url: VARIABLE_API.DELETE, data }, {
isReturnNativeResponse: true });
}
+
/**
* Code check
* @param {Object} data
@@ -72,3 +74,12 @@ export function fetchCheckVariableCode(data: {
}): Promise<AxiosResponse<Result>> {
return defHttp.post({ url: VARIABLE_API.CHECK_CODE, data }, {
isReturnNativeResponse: true });
}
+
+/**
+ * Code check
+ * @param {Object} data
+ * @returns {Promise<AxiosResponse<Result>>}
+ */
+export function fetchDependApps(data: Recordable): Promise<any> {
+ return defHttp.post({ url: VARIABLE_API.DEPEND, data });
+}
diff --git
a/streampark-console/streampark-console-newui/src/components/CardList/src/CardList.vue
b/streampark-console/streampark-console-newui/src/components/CardList/src/CardList.vue
index ca8571442..a11104d9b 100644
---
a/streampark-console/streampark-console-newui/src/components/CardList/src/CardList.vue
+++
b/streampark-console/streampark-console-newui/src/components/CardList/src/CardList.vue
@@ -26,8 +26,8 @@
:pagination="paginationProp"
>
<template #header>
- <div class="flex justify-end space-x-2"
- ><slot name="header"></slot>
+ <div class="flex justify-end space-x-2">
+ <slot name="header"></slot>
<Tooltip>
<template #title>
<div class="w-50">Display quantity per line</div
diff --git a/streampark-console/streampark-console-newui/src/design/public.less
b/streampark-console/streampark-console-newui/src/design/public.less
index bbaa20016..6268fac5b 100644
--- a/streampark-console/streampark-console-newui/src/design/public.less
+++ b/streampark-console/streampark-console-newui/src/design/public.less
@@ -24,8 +24,8 @@
// =================================
::-webkit-scrollbar {
- width: 14px;
- height: 12px;
+ width: 7px;
+ height: 8px;
}
// ::-webkit-scrollbar-track {
@@ -33,21 +33,21 @@
// }
::-webkit-scrollbar-track {
- // background-color: rgb(0 0 0 / 5%);
- background-color: unset;
+ background-color: rgb(0 0 0 / 5%);
}
-::-webkit-scrollbar-thumb:hover,
::-webkit-scrollbar-thumb {
- background-color: #e6f7ff;
+ // background: rgba(0, 0, 0, 0.6);
+ background-color: rgb(144 147 153 / 30%);
+ // background-color: rgba(144, 147, 153, 0.3);
+ border-radius: 2px;
+ box-shadow: inset 0 0 6px rgb(0 0 0 / 20%);
}
-[data-theme="dark"] {
- ::-webkit-scrollbar-thumb:hover,
- ::-webkit-scrollbar-thumb {
- background-color: #2a2a2a;
- }
+::-webkit-scrollbar-thumb:hover {
+ background-color: @border-color-dark;
}
+
// =================================
// ==============nprogress==========
// =================================
diff --git
a/streampark-console/streampark-console-newui/src/layouts/default/footer/index.vue
b/streampark-console/streampark-console-newui/src/layouts/default/footer/index.vue
index c1e556543..726f92b1a 100644
---
a/streampark-console/streampark-console-newui/src/layouts/default/footer/index.vue
+++
b/streampark-console/streampark-console-newui/src/layouts/default/footer/index.vue
@@ -24,7 +24,8 @@
<!-- <a @click="openWindow(DOC_URL)">{{
t('layout.footer.onlineDocument') }}</a> -->
</div>
<div :class="`${prefixCls}__copyright`">
- Copyright ©2019~{{ new Date().getFullYear() }} {{ title }}
+ Copyright ©{{ new Date().getFullYear() }} The Apache Software
Foundation. Apache
+ StreamPark, StreamPark, and its feather logo are trademarks of The
Apache Software Foundation
</div>
</Footer>
</template>
@@ -43,7 +44,6 @@
import { useRouter } from 'vue-router';
import { useDesign } from '/@/hooks/web/useDesign';
import { useLayoutHeight } from '../content/useContentViewHeight';
- import { useGlobSetting } from '/@/hooks/setting';
export default defineComponent({
name: 'LayoutFooter',
@@ -53,7 +53,6 @@
const { getShowFooter } = useRootSetting();
const { currentRoute } = useRouter();
const { prefixCls } = useDesign('layout-footer');
- const { title } = useGlobSetting();
const footerRef = ref<ComponentRef>(null);
const { setFooterHeight } = useLayoutHeight();
@@ -76,7 +75,6 @@
SITE_URL,
openWindow,
footerRef,
- title,
};
},
});
diff --git a/streampark-console/streampark-console-newui/src/router/constant.ts
b/streampark-console/streampark-console-newui/src/router/constant.ts
index b92c90f8a..c3448b591 100644
--- a/streampark-console/streampark-console-newui/src/router/constant.ts
+++ b/streampark-console/streampark-console-newui/src/router/constant.ts
@@ -40,6 +40,8 @@ export const getParentLayout = (_name?: string) => {
};
const projectPath = '/flink/project';
const settingPath = '/flink/setting';
+const variablePath = '/system/variable';
+
const applicationPath = '/flink/app';
export const menuMap = {
[`${projectPath}/add`]: projectPath,
@@ -51,4 +53,5 @@ export const menuMap = {
[`${applicationPath}/edit_streampark`]: applicationPath,
[`${settingPath}/add_cluster`]: settingPath,
[`${settingPath}/edit_cluster`]: settingPath,
+ [`${variablePath}/depend_apps`]: variablePath,
};
diff --git
a/streampark-console/streampark-console-newui/src/router/guard/permissionGuard.ts
b/streampark-console/streampark-console-newui/src/router/guard/permissionGuard.ts
index 3dcbd321d..4a931a342 100644
---
a/streampark-console/streampark-console-newui/src/router/guard/permissionGuard.ts
+++
b/streampark-console/streampark-console-newui/src/router/guard/permissionGuard.ts
@@ -46,7 +46,6 @@ export function createPermissionGuard(router: Router) {
}
const token = userStore.getToken;
-
// Whitelist can be directly entered
if (whitePathList.includes(to.path as PageEnum)) {
if (to.path === LOGIN_PATH && token) {
diff --git
a/streampark-console/streampark-console-newui/src/settings/projectSetting.ts
b/streampark-console/streampark-console-newui/src/settings/projectSetting.ts
index f63a14cd2..7dd2a2936 100644
--- a/streampark-console/streampark-console-newui/src/settings/projectSetting.ts
+++ b/streampark-console/streampark-console-newui/src/settings/projectSetting.ts
@@ -43,7 +43,7 @@ const setting: ProjectConfig = {
permissionMode: PermissionModeEnum.BACK,
// Permission-related cache is stored in sessionStorage or localStorage
- permissionCacheType: CacheTypeEnum.LOCAL,
+ permissionCacheType: CacheTypeEnum.SESSION,
// Session timeout processing
sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
diff --git
a/streampark-console/streampark-console-newui/src/store/modules/permission.ts
b/streampark-console/streampark-console-newui/src/store/modules/permission.ts
index da57124a8..19c7ddbd3 100644
---
a/streampark-console/streampark-console-newui/src/store/modules/permission.ts
+++
b/streampark-console/streampark-console-newui/src/store/modules/permission.ts
@@ -40,9 +40,10 @@ import { getPermCode } from '/@/api/system/user';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageEnum } from '/@/enums/pageEnum';
import { fetchUserTeam } from '/@/api/system/member';
-import { Persistent } from '/@/utils/cache/persistent';
+// import { Persistent } from '/@/utils/cache/persistent';
import { USER_INFO_KEY } from '/@/enums/cacheEnum';
import { UserInfo } from '/#/store';
+import { getAuthCache } from '/@/utils/auth';
interface PermissionState {
// Permission code list
@@ -126,7 +127,7 @@ export const usePermissionStore = defineStore({
const userStore = useUserStore();
const appStore = useAppStoreWithOut();
// get teamList
- const { userId } = Persistent.getLocal(USER_INFO_KEY) as UserInfo;
+ const { userId } = getAuthCache(USER_INFO_KEY) as UserInfo;
if (userStore.teamList.length == 0 && userId) {
const teamList = await fetchUserTeam({ userId });
userStore.setTeamList(teamList.map((i) => ({ label: i.teamName, value:
i.id })));
@@ -239,6 +240,7 @@ export const usePermissionStore = defineStore({
title: t('sys.api.errorTip'),
content: 'No permission, please contact the administrator',
});
+ userStore.logout();
return Promise.reject(new Error('routeList is empty'));
}
routeList = (routeList[0].children as AppRouteRecordRaw[]).map((v)
=> {
diff --git
a/streampark-console/streampark-console-newui/src/store/modules/user.ts
b/streampark-console/streampark-console-newui/src/store/modules/user.ts
index a99b307ac..cdb1dab57 100644
--- a/streampark-console/streampark-console-newui/src/store/modules/user.ts
+++ b/streampark-console/streampark-console-newui/src/store/modules/user.ts
@@ -38,8 +38,6 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
import { h } from 'vue';
import { getUserTeamId } from '/@/utils';
import { usePermission } from '/@/hooks/web/usePermission';
-import { AesEncryption } from '/@/utils/cipher';
-import { cacheCipher } from '/@/settings/encryptionSetting';
interface TeamListType {
label: string;
@@ -112,13 +110,6 @@ export const useUserStore = defineStore({
setToken(info: string | undefined) {
this.token = info ? info : ''; // for null or undefined value
setAuthCache(TOKEN_KEY, info);
- let cacheToken = this.token;
- // production encrypted
- if (import.meta.env.PROD && cacheToken) {
- const encryption = new AesEncryption({ key: cacheCipher.key, iv:
cacheCipher.iv });
- cacheToken = encryption.encryptByAES(cacheToken);
- }
- localStorage.setItem(TOKEN_KEY, cacheToken);
},
setExpire(info: string | undefined) {
this.expire = info || '';
@@ -149,12 +140,11 @@ export const useUserStore = defineStore({
setData(data: Recordable) {
const { token, expire, user, permissions, roles = [] } = data;
+ this.setToken(token);
this.setExpire(expire);
this.setUserInfo(user);
this.setRoleList(roles);
this.setPermissions(permissions);
- // set token must be placed at the end, need to listen to this value
- this.setToken(token);
},
// set team
async setTeamId(data: { teamId: string; userId?: string }):
Promise<boolean> {
diff --git
a/streampark-console/streampark-console-newui/src/utils/auth/index.ts
b/streampark-console/streampark-console-newui/src/utils/auth/index.ts
index ecd313c46..81bc699b0 100644
--- a/streampark-console/streampark-console-newui/src/utils/auth/index.ts
+++ b/streampark-console/streampark-console-newui/src/utils/auth/index.ts
@@ -27,16 +27,33 @@ export function getToken() {
}
export function getAuthCache<T>(key: BasicKeys) {
- const fn = isLocal ? Persistent.getLocal : Persistent.getSession;
- return fn(key) as T;
+ if (isLocal) {
+ return Persistent.getLocal(key) as T;
+ } else {
+ const sessionCacheValue = Persistent.getSession(key) as T;
+ const localCacheValue = Persistent.getLocal(key) as T;
+ if (!sessionCacheValue && localCacheValue) {
+ Persistent.setSession(key, localCacheValue, true);
+ return localCacheValue;
+ }
+ return sessionCacheValue;
+ }
}
export function setAuthCache(key: BasicKeys, value) {
- const fn = isLocal ? Persistent.setLocal : Persistent.setSession;
- return fn(key, value, true);
+ if (isLocal) {
+ return Persistent.setLocal(key, value, true);
+ } else {
+ Persistent.setLocal(key, value, true);
+ return Persistent.setSession(key, value, true);
+ }
}
export function clearAuthCache(immediate = true) {
- const fn = isLocal ? Persistent.clearLocal : Persistent.clearSession;
- return fn(immediate);
+ if (isLocal) {
+ return Persistent.clearLocal(immediate);
+ } else {
+ Persistent.clearLocal(immediate);
+ return Persistent.clearSession(immediate);
+ }
}
diff --git
a/streampark-console/streampark-console-newui/src/utils/cache/persistent.ts
b/streampark-console/streampark-console-newui/src/utils/cache/persistent.ts
index 4488d17e3..0cb495c5d 100644
--- a/streampark-console/streampark-console-newui/src/utils/cache/persistent.ts
+++ b/streampark-console/streampark-console-newui/src/utils/cache/persistent.ts
@@ -135,17 +135,6 @@ function storageChange(e: any) {
Persistent.clearAll();
return;
}
- // token change reload
- if (key === TOKEN_KEY && oldValue !== newValue) {
- const { [TOKEN_KEY]: tokenCache } = pick(ls.get(APP_LOCAL_CACHE_KEY),
TOKEN_KEY);
- // no token or token value is invalid
- if (tokenCache?.value !== newValue) {
- Persistent.clearLocal();
- return;
- }
- window.location.reload();
- return;
- }
if (!!newValue && !!oldValue) {
if (APP_LOCAL_CACHE_KEY === key) {
Persistent.clearLocal();
diff --git
a/streampark-console/streampark-console-newui/src/views/base/login/Login.vue
b/streampark-console/streampark-console-newui/src/views/base/login/Login.vue
index dfcde4316..9295de01c 100644
--- a/streampark-console/streampark-console-newui/src/views/base/login/Login.vue
+++ b/streampark-console/streampark-console-newui/src/views/base/login/Login.vue
@@ -21,8 +21,9 @@
<div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0">
<div
:class="`${prefixCls}-form`"
- class="relative w-auto px-12 bg-[rgba(0,0,0,0.4)] py-5 mx-auto
my-auto shadow-md enter-y">
- <LoginForm/>
+ class="relative w-auto px-12 bg-[rgba(0,0,0,0.4)] py-5 mx-auto
my-auto shadow-md enter-y"
+ >
+ <LoginForm />
</div>
</div>
</div>
@@ -30,137 +31,144 @@
</div>
</template>
<script lang="ts" setup>
-import LoginForm from './LoginForm.vue';
-import ForgetPasswordForm from './ForgetPasswordForm.vue';
-import {useDesign} from '/@/hooks/web/useDesign';
-
-defineProps({
- sessionTimeout: {
- type: Boolean,
- },
-});
-
-// const globSetting = useGlobSetting();
-const {prefixCls} = useDesign('login');
-// const title = computed(() => globSetting?.title ?? '');
+ import LoginForm from './LoginForm.vue';
+ import { useDesign } from '/@/hooks/web/useDesign';
+
+ defineProps({
+ sessionTimeout: {
+ type: Boolean,
+ },
+ });
+
+ // const globSetting = useGlobSetting();
+ const { prefixCls } = useDesign('login');
+ // const title = computed(() => globSetting?.title ?? '');
</script>
<style lang="less">
-@prefix-cls: ~'@{namespace}-login';
-@logo-prefix-cls: ~'@{namespace}-app-logo';
-@countdown-prefix-cls: ~'@{namespace}-countdown-input';
-@active-color: 255, 255, 255;
-
-input.fix-auto-fill, .fix-auto-fill input {
- box-shadow: inherit !important;
-}
-
-.@{prefix-cls} {
- min-height: 100%;
- overflow: hidden;
- background: url('/@/assets/images/sign-bg.jpg') no-repeat 50%;
- background-size: cover;
-
- .ant-input-affix-wrapper {
- border: 1px solid rgba(@active-color, 0.55);
- border-radius: 1px;
- color: rgba(@active-color, 0.65);
- margin-top: 10px;
- background-color: rgba(@active-color, 0.05) !important;
+ @prefix-cls: ~'@{namespace}-login';
+ @logo-prefix-cls: ~'@{namespace}-app-logo';
+ @countdown-prefix-cls: ~'@{namespace}-countdown-input';
+ @active-color: 255, 255, 255;
+
+ input.fix-auto-fill,
+ .fix-auto-fill input {
+ box-shadow: inherit !important;
}
- .signin-title {
- padding-top: 20px;
- font-size: 16px;
- color: rgba(255, 255, 255, 0.65);
- margin-top: 12px;
- margin-bottom: 20px;
- }
+ .@{prefix-cls} {
+ min-height: 100%;
+ overflow: hidden;
+ background: url('/@/assets/images/sign-bg.jpg') no-repeat 50%;
+ background-size: cover;
+
+ .ant-input-affix-wrapper {
+ border: 1px solid rgba(@active-color, 0.55);
+ border-radius: 1px;
+ color: rgba(@active-color, 0.65);
+ margin-top: 10px;
+ background-color: rgba(@active-color, 0.05) !important;
+ }
- .logo {
- padding-top: 20px;
- height: 130px;
- margin: auto;
- }
+ .signin-title {
+ padding-top: 20px;
+ font-size: 16px;
+ color: rgba(255, 255, 255, 0.65);
+ margin-top: 12px;
+ margin-bottom: 20px;
+ }
- .signin-form {
- .ant-input {
- padding-top: 3px;
- padding-bottom: 3px;
+ .logo {
+ padding-top: 20px;
+ height: 130px;
+ margin: auto;
+ }
- .ant-input-affix-wrapper:hover, .ant-input:not(.ant-input-disabled) {
- border-color: rgba(@active-color, .95);
+ .signin-form {
+ .ant-form-item-has-error
:not(.ant-input-disabled):not(.ant-input-borderless).ant-input {
+ background-color: transparent !important;
}
- }
- .signin-btn {
- .ant-btn {
- margin-top: 30px;
- height: 40px;
- background: rgba(@active-color, .40);
- border: unset;
+ .ant-input {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ color: @white;
+
+ .ant-input-affix-wrapper:hover,
+ .ant-input:not(.ant-input-disabled) {
+ border-color: rgba(@active-color, 0.95);
+ }
+ }
+ .ant-input-password-icon {
+ color: @content-bg !important;
+ }
+ .signin-btn {
+ .ant-btn {
+ margin-top: 30px;
+ height: 40px;
+ background: rgba(@active-color, 0.4);
+ border: unset;
+ }
}
- }
- .text-left {
- .ant-btn {
- padding: 0px;
+ .text-left {
+ .ant-btn {
+ padding: 0px;
+ }
}
}
- }
+ &::after {
+ content: '';
+ width: 100%;
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: -20px;
+ background: inherit;
+ z-index: 2;
+ filter: blur(1px);
+ }
- &::after {
- content: '';
- width: 100%;
- position: absolute;
- left: 0;
- top: 0;
- bottom: -20px;
- background: inherit;
- z-index: 2;
- filter: blur(1px);
- }
+ &-sign-in-way {
+ .anticon {
+ font-size: 22px;
+ color: #888;
+ cursor: pointer;
+ &:hover {
+ color: @primary-color;
+ }
+ }
+ }
- &-sign-in-way {
- .anticon {
- font-size: 22px;
- color: #888;
- cursor: pointer;
+ input {
+ min-width: 300px;
+ background: transparent;
- &:hover {
- color: @primary-color;
+ @media (max-width: @screen-xl) {
+ min-width: 260px;
}
- }
- }
- input {
- min-width: 300px;
+ @media (max-width: @screen-lg) {
+ min-width: 200px;
+ }
- @media (max-width: @screen-xl) {
- min-width: 260px;
- }
+ @media (max-width: @screen-md) {
+ min-width: 180px;
+ }
- @media (max-width: @screen-lg) {
- min-width: 200px;
+ @media (max-width: @screen-sm) {
+ min-width: 100px;
+ }
}
- @media (max-width: @screen-md) {
- min-width: 180px;
+ .@{countdown-prefix-cls} input {
+ min-width: unset;
}
- @media (max-width: @screen-sm) {
- min-width: 100px;
+ .ant-divider-inner-text {
+ font-size: 12px;
+ color: @text-color-secondary;
}
}
-
- .@{countdown-prefix-cls} input {
- min-width: unset;
- }
-
- .ant-divider-inner-text {
- font-size: 12px;
- color: @text-color-secondary;
- }
-}
</style>
diff --git
a/streampark-console/streampark-console-newui/src/views/base/login/LoginForm.vue
b/streampark-console/streampark-console-newui/src/views/base/login/LoginForm.vue
index 98f36c91c..f86fc1d70 100644
---
a/streampark-console/streampark-console-newui/src/views/base/login/LoginForm.vue
+++
b/streampark-console/streampark-console-newui/src/views/base/login/LoginForm.vue
@@ -23,12 +23,14 @@
ref="formRef"
v-show="getShow"
@keypress.enter="handleLogin"
+ autocomplete="off"
>
<FormItem name="account" class="enter-x">
<Input
v-model:value="formData.account"
:placeholder="t('sys.login.userName')"
- class="fix-auto-fill">
+ class="fix-auto-fill"
+ >
<template #prefix>
<user-outlined type="user" />
</template>
@@ -38,7 +40,8 @@
<InputPassword
visibilityToggle
v-model:value="formData.password"
- :placeholder="t('sys.login.password')">
+ :placeholder="t('sys.login.password')"
+ >
<template #prefix>
<lock-outlined type="user" />
</template>
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/app/EditStreamPark.vue
b/streampark-console/streampark-console-newui/src/views/flink/app/EditStreamPark.vue
index b6ad353f8..75d93984d 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/app/EditStreamPark.vue
+++
b/streampark-console/streampark-console-newui/src/views/flink/app/EditStreamPark.vue
@@ -69,7 +69,7 @@
tmPodTemplate: '',
});
const { handleResetApplication, defaultOptions } = useEdit();
- const { getEditStreamParkFormSchema, registerDifferentDrawer, alerts,
flinkEnvs } =
+ const { getEditStreamParkFormSchema, registerDifferentDrawer, alerts,
flinkEnvs, flinkClusters } =
useEditStreamParkSchema(configVersions, flinkSqlHistory, dependencyRef);
const [registerForm, { setFieldsValue, getFieldsValue, submit }] = useForm({
@@ -169,7 +169,15 @@
if (values.uploadJars != null && values.uploadJars.length > 0) {
Object.assign(dependency, { jar: values.dependency });
}
-
+ if (values.yarnSessionClusterId) {
+ const cluster =
+ flinkClusters.value.filter(
+ (c) => c.clusterId === values.yarnSessionClusterId &&
c.clusterState === 1,
+ )[0] || null;
+ values.clusterId = cluster.id;
+ values.flinkClusterId = cluster.id;
+ values.yarnSessionClusterId = cluster.clusterId;
+ }
let config = values.configOverride;
if (config != null && config.trim() !== '') {
config = decodeByBase64(config);
@@ -204,6 +212,15 @@
} else {
config = null;
}
+ if (values.yarnSessionClusterId) {
+ const cluster =
+ flinkClusters.value.filter(
+ (c) => c.clusterId === values.yarnSessionClusterId &&
c.clusterState === 1,
+ )[0] || null;
+ values.clusterId = cluster.id;
+ values.flinkClusterId = cluster.id;
+ values.yarnSessionClusterId = cluster.clusterId;
+ }
const configId = values.strategy === 1 ? app.configId : null;
const params = {
id: app.id,
@@ -238,13 +255,15 @@
const appId = route.query.appId;
const res = await fetchGet({ id: appId as string });
let configId = '';
- const confVersion = await fetchConfHistory({ id: route.query.appId });
- confVersion.forEach((value) => {
- if (value.effective) {
- configId = value.id;
- }
+ fetchConfHistory({ id: route.query.appId }).then((confVersion) => {
+ confVersion.forEach((value) => {
+ if (value.effective) {
+ configId = value.id;
+ }
+ });
+ configVersions.value = confVersion;
});
- configVersions.value = confVersion;
+
Object.assign(app, res);
Object.assign(defaultOptions, JSON.parse(app.options || '{}'));
setFieldsValue({
@@ -261,8 +280,9 @@
unref(flinkSql)?.setContent(decodeByBase64(res.flinkSql));
});
if (app.jobType === 2) {
- const res = await fetchFlinkHistory({ id: appId });
- flinkSqlHistory.value = res;
+ fetchFlinkHistory({ id: appId }).then((res) => {
+ flinkSqlHistory.value = res;
+ });
}
if (app.alertId) {
selectAlertId.value = unref(alerts).filter((t) => t.id ==
app.alertId)[0]?.id;
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/app/data/index.ts
b/streampark-console/streampark-console-newui/src/views/flink/app/data/index.ts
index 17196c0ee..c1a6eaa07 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/app/data/index.ts
+++
b/streampark-console/streampark-console-newui/src/views/flink/app/data/index.ts
@@ -63,7 +63,7 @@ export const getAppColumns = (): BasicColumn[] => [
{ text: 'ADDED', value: '0' },
{ text: 'STARTING', value: '3' },
{ text: 'RUNNING', value: '5' },
- { text: 'FAILED', value: '6' },
+ { text: 'FAILED', value: '7' },
{ text: 'CANCELED', value: '9' },
{ text: 'FINISHED', value: '10' },
{ text: 'LOST', value: '13' },
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/View.less
b/streampark-console/streampark-console-newui/src/views/flink/setting/View.less
index 66bcca94c..9d0ffb837 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/View.less
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/View.less
@@ -22,7 +22,7 @@
.system-setting {
.ant-card-body {
- padding: 0 24px !important;
+ padding: 0 24px;
}
.collapse {
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/View.vue
b/streampark-console/streampark-console-newui/src/views/flink/setting/View.vue
index 2c158b34c..016aa178e 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/View.vue
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/View.vue
@@ -24,7 +24,11 @@
</Card>
</TabPane>
<TabPane tab="Alert Setting" key="alert">
- <Card :bordered="false" class="system-setting">
+ <Card
+ :bordered="false"
+ class="system-setting !bg-transparent"
+ :body-style="{ padding: 0 }"
+ >
<AlertSetting />
</Card>
</TabPane>
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertModal.vue
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertModal.vue
index fa405f5bd..014e802e8 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertModal.vue
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertModal.vue
@@ -15,19 +15,17 @@
limitations under the License.
-->
<script lang="ts">
- import { defineComponent } from 'vue';
- import { omit } from 'lodash-es';
- import { alertFormSchema } from './alert.data';
-
export default defineComponent({
name: 'AlertModal',
});
</script>
<script setup lang="ts" name="AlertModal">
- import { ref } from 'vue';
+ import { ref, defineComponent, h } from 'vue';
+ import { omit } from 'lodash-es';
+ import { alertFormSchema, alertTypes } from './alert.data';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form';
- import { Form, Select, Input, Divider, Tooltip, Switch } from
'ant-design-vue';
+ import { Form, Select, Input, Divider } from 'ant-design-vue';
import { SvgIcon } from '/@/components/Icon';
import { fetchAlertAdd, fetchAlertUpdate, fetchExistsAlert } from
'/@/api/flink/setting/alert';
import { useUserStore } from '/@/store/modules/user';
@@ -39,16 +37,7 @@
const emit = defineEmits(['reload', 'register']);
const alertId = ref<string | null>(null);
- const alertTypes = ref([
- { name: 'E-mail', value: 1, disabled: false, icon: 'mail' },
- { name: 'Ding Talk', value: 2, disabled: false, icon: 'dingtalk' },
- { name: 'Wechat', value: 4, disabled: false, icon: 'wecom' },
- { name: 'SMS', value: 8, disabled: true, icon: 'message' },
- { name: 'Lark', value: 16, disabled: false, icon: 'lark' },
- ]);
- const alertType = ref<number[]>([]);
- const dingtalkSecretEnable = ref(false);
- const larkSecretEnable = ref(false);
+ const alertType = ref<string[]>([]);
const { Swal } = useMessage();
const userStore = useUserStore();
@@ -65,9 +54,11 @@
label: 'Alert Name',
component: 'Input',
componentProps: { allowClear: true, placeholder: 'Please enter alert
name' },
- colProps: {
- style: { marginBottom: '20px' },
- },
+ itemExtra: h(
+ 'span',
+ { class: 'conf-switch' },
+ 'the alert name, e.g: StreamPark team alert',
+ ),
dynamicRules: () => {
return [
{
@@ -117,6 +108,7 @@
try {
changeOkLoading(true);
const formValue = await validateFields();
+ console.log('formValue', formValue);
const param = {
id: alertId.value,
alertName: formValue.alertName,
@@ -212,170 +204,88 @@
placeholder="Alert Type"
allowClear
mode="multiple"
- @change="(value:number[])=>alertType=value"
+ @change="(value:string[])=>alertType=value"
>
<SelectOption
- v-for="(o, index) in alertTypes"
- :key="`alertType_${index}`"
- :disabled="o.disabled"
- :value="o.value"
+ v-for="(v, k) in alertTypes"
+ :key="`alertType_${k}`"
+ :disabled="v.disabled"
+ :value="k"
>
- <SvgIcon :name="o.icon" />
- {{ o.name }}
+ <SvgIcon :name="v.icon" />
+ {{ v.name }}
</SelectOption>
</Select>
</template>
-
+ {{ alertType }}
<template #alertEmail="{ model, field }">
<!-- Alert Email -->
- <Divider v-if="alertType.indexOf(1) > -1">
- <SvgIcon name="mail" size="20" />
- E-mail
- </Divider>
- <FormItem
- v-if="alertType.indexOf(1) > -1"
- label="Alert Email"
- :rules="[{ required: true, message: 'email address is required',
trigger: 'blur' }]"
- name="alertEmail"
- >
- <Input
- v-model:value="model[field]"
- placeholder="Please enter email,separate multiple emails with
comma(,)"
- />
- </FormItem>
+ <template v-if="(alertType || []).includes('1')">
+ <Divider>
+ <SvgIcon name="mail" size="20" />
+ E-mail
+ </Divider>
+ <FormItem
+ label="Alert Email"
+ :rules="[
+ { required: true, message: 'email address is required', trigger:
'blur' },
+ { type: 'email', message: 'Incorrect format', trigger: 'blur' },
+ ]"
+ name="alertEmail"
+ >
+ <Input
+ v-model:value="model[field]"
+ placeholder="Please enter email,separate multiple emails with
comma(,)"
+ />
+ </FormItem>
+ </template>
</template>
- <template #alertDingURL="{ model, field }" v-if="alertType.indexOf(2) >
-1">
- <Divider v-if="alertType.indexOf(2) > -1">
+ <template #alertDingURL="{ model, field }" v-if="(alertType ||
[]).includes('2')">
+ <Divider>
<SvgIcon name="dingtalk" size="20" />
Ding Talk
</Divider>
<FormItem
label="DingTalk Url"
- defaultValue="https://oapi.dingtalk.com/robot/send"
- name="alertEmail"
+ name="alertDingURL"
+ :rules="[
+ {
+ pattern:
+
/^((https?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/,
+ message: 'Incorrect format',
+ trigger: 'blur',
+ },
+ ]"
>
<Input v-model:value="model[field]" placeholder="Please enter
DingTask Url" allowClear />
</FormItem>
</template>
- <template #dingtalkToken="{ model, field }" v-if="alertType.indexOf(2) >
-1">
- <FormItem
- label="Access Token"
- name="dingtalkToken"
- :rules="[{ required: true, message: 'Access token is required' }]"
- >
- <Input
- v-model:value="model[field]"
- placeholder="Please enter the access token of DingTalk"
- allowClear
- />
- </FormItem>
- </template>
-
- <template #dingtalkSecretEnable="{ model, field }"
v-if="alertType.indexOf(2) > -1">
- <FormItem label="Secret Enable" name="dingtalkSecretEnable">
- <Tooltip title="DingTalk ecretToken is enable">
- <Switch
- v-model:checked="model[field]"
- checked-children="ON"
- un-checked-children="OFF"
- allowClear
- @change="(checked:boolean) => (dingtalkSecretEnable = checked)"
- />
- </Tooltip>
- </FormItem>
- </template>
- <!-- Secret Token -->
- <template
- #dingtalkSecretToken="{ model, field }"
- v-if="alertType.indexOf(2) > -1 && dingtalkSecretEnable"
- >
- <FormItem
- label="Secret Token"
- name="dingtalkSecretToken"
- :rules="[{ required: true, message: 'DingTalk SecretToken is
required' }]"
- >
- <Input
- v-model:value="model[field]"
- placeholder="Please enter DingTalk SecretToken"
- allowClear
- />
- </FormItem>
- </template>
-
- <!-- DingTalk User -->
- <template #alertDingUser="{ model, field }" v-if="alertType.indexOf(2) >
-1">
- <FormItem label="DingTalk User" name="alertDingUser">
- <Input
- v-model:value="model[field]"
- placeholder="Please enter DingTalk receive user"
- allowClear
- />
- </FormItem>
- </template>
-
- <!-- At All User -->
- <template #dingtalkIsAtAll="{ model, field }" v-if="alertType.indexOf(2)
> -1">
- <FormItem label="At All User">
- <Tooltip title="Whether Notify All">
- <Switch
- v-model:checked="model[field]"
- checked-children="ON"
- un-checked-children="OFF"
- />
- </Tooltip>
- </FormItem>
- </template>
-
<!-- WeChat -->
- <template #weToken="{ model, field, schema }" v-if="alertType.indexOf(4)
> -1">
+ <template #weToken="{ model, field, schema }" v-if="(alertType ||
[]).includes('4')">
<Divider><SvgIcon name="wecom" size="20" /> WeChat </Divider>
<FormItem :label="schema.label" :name="field" :rules="schema.rules">
- <Input v-model:value="model[field]" v-bind="schema.componentProps" />
+ <InputTextArea v-model:value="model[field]"
v-bind="schema.componentProps" />
</FormItem>
</template>
- <template #alertSms="{ model, field, schema }"
v-if="alertType.indexOf(8) > -1">
+ <template #alertSms="{ model, field, schema }" v-if="(alertType ||
[]).includes('8')">
<Divider><SvgIcon name="message" size="20" /> SMS </Divider>
<FormItem :label="schema.label" :name="field" :rules="schema.rules">
<Input v-model:value="model[field]" v-bind="schema.componentProps" />
</FormItem>
</template>
- <template #alertSmsTemplate="{ model, field, schema }"
v-if="alertType.indexOf(8) > -1">
- <FormItem :label="schema.label" :name="field" :rules="schema.rules">
- <InputTextArea v-model:value="model[field]"
v-bind="schema.componentProps" />
- </FormItem>
- </template>
-
- <template #larkToken="{ model, field, schema }"
v-if="alertType.indexOf(16) > -1">
+ <!-- lark -->
+ <template #larkToken="{ model, field, schema }" v-if="(alertType ||
[]).includes('16')">
<Divider><SvgIcon name="lark" size="20" /> Lark </Divider>
<FormItem :label="schema.label" :name="field" :rules="schema.rules">
- <Input v-model:value="model[field]" v-bind="schema.componentProps" />
- </FormItem>
- </template>
-
- <template #larkIsAtAll="{ model, field, schema }"
v-if="alertType.indexOf(16) > -1">
- <FormItem :label="schema.label" :name="field" :rules="schema.rules">
- <Tooltip title="Whether Notify All">
- <Switch
- checked-children="ON"
- un-checked-children="OFF"
- allowClear
- v-model:checked="model[field]"
- @change="(checked:boolean) => (larkSecretEnable = checked)"
- />
- </Tooltip>
- </FormItem>
- </template>
-
- <template
- #larkSecretToken="{ model, field, schema }"
- v-if="alertType.indexOf(16) > -1 && larkSecretEnable"
- >
- <FormItem :label="schema.label" :name="field" :rules="schema.rules">
- <Input v-bind="schema.componentProps" v-model:checked="model[field]"
/>
+ <Input
+ v-model:value="model[field]"
+ placeholder="Please enter the access token of LarkTalk"
+ allow-clear
+ />
</FormItem>
</template>
</BasicForm>
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertSetting.vue
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertSetting.vue
index f6b401900..5b5c9decd 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertSetting.vue
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertSetting.vue
@@ -24,7 +24,7 @@
</script>
<script setup lang="ts" name="AlertSetting">
import { onMounted, ref } from 'vue';
- import { List, Popconfirm, Tooltip } from 'ant-design-vue';
+ import { List, Popconfirm, Tooltip, Card, Tag } from 'ant-design-vue';
import {
ThunderboltOutlined,
EditOutlined,
@@ -32,35 +32,42 @@
PlusOutlined,
} from '@ant-design/icons-vue';
import { useModal } from '/@/components/Modal';
- import { SvgIcon } from '/@/components/Icon';
import AlertModal from './AlertModal.vue';
import { fetchAlertSetting, fetchSendAlert, fetchAlertDelete } from
'/@/api/flink/setting/alert';
import { AlertSetting } from '/@/api/flink/setting/types/alert.type';
import { useMessage } from '/@/hooks/web/useMessage';
+ import AlertTypeInfo from './AlertTypeInfo.vue';
const ListItem = List.Item;
- const ListItemMeta = ListItem.Meta;
const { t } = useI18n();
const { Swal, createMessage } = useMessage();
const [registerAlertModal, { openModal: openAlertModal }] = useModal();
const alerts = ref<AlertSetting[]>([]);
- const alertType = ref<number[]>([]);
+
/* Get alert configuration */
async function getAlertSetting() {
const res = await fetchAlertSetting();
+ res.map((a) => (a.alertTypeTags = computeAlertType(a.alertType)));
alerts.value = res;
}
+ const alertTypeMap = {
+ 1: 'mail',
+ 2: 'dingtalk',
+ 4: 'wecom',
+ 8: 'message',
+ 16: 'lark',
+ };
/* compute type */
function computeAlertType(level: number) {
if (level === null) {
level = 0;
}
- const result: number[] = [];
+ const result: string[] = [];
while (level != 0) {
// Get the lowest 1
const code = level & -level;
- result.push(code);
+ result.push(String(code));
// Set the lowest position to 0
level ^= code;
}
@@ -86,24 +93,22 @@
}
/* Click the edit button */
function handleEditAlertConf(item: AlertSetting) {
- alertType.value = computeAlertType(item.alertType);
-
let emailParams: Recordable<any> = {};
let dingTalkParams: Recordable<any> = {};
let weComParams: Recordable<any> = {};
let larkParams: Recordable<any> = {};
- if (alertType.value.indexOf(1) > -1) {
+ if (item.alertTypeTags?.includes('1')) {
emailParams = JSON.parse(item.emailParams);
}
- if (alertType.value.indexOf(2) > -1) {
+ if (item.alertTypeTags?.includes('2')) {
dingTalkParams = JSON.parse(item.dingTalkParams);
// dingtalkIsAtAll = dingTalkParams.isAtAll;
// dingtalkSecretEnable = dingTalkParams.secretEnable;
}
- if (alertType.value.indexOf(4) > -1) {
+ if (item.alertTypeTags?.includes('4')) {
weComParams = JSON.parse(item.weComParams) as Recordable;
}
- if (alertType.value.indexOf(16) > -1) {
+ if (item.alertTypeTags?.includes('16')) {
larkParams = JSON.parse(item.larkParams) as Recordable;
// larkIsAtAll = larkParams.isAtAll;
// larkSecretEnable = larkParams.secretEnable;
@@ -113,7 +118,7 @@
openAlertModal(true, {
alertId: item.id,
alertName: item.alertName,
- alertType: alertType.value,
+ alertType: item.alertTypeTags,
alertEmail: emailParams.contacts,
alertDingURL: dingTalkParams.alertDingURL,
dingtalkToken: dingTalkParams.token,
@@ -153,75 +158,133 @@
console.error(error);
}
}
+
+ function getAlertTypeName(type: number) {
+ return alertTypeMap[type] || '';
+ }
+
onMounted(() => {
getAlertSetting();
});
</script>
<template>
- <div v-auth="'project:create'">
+ <div v-auth="'project:create'" class="bg-white p-10px">
<a-button type="dashed" style="width: 100%; margin-top: 20px"
@click="openAlertModal(true, {})">
<PlusOutlined />
{{ t('common.add') }}
</a-button>
</div>
- <List>
- <ListItem v-for="(item, index) in alerts" :key="index">
- <ListItemMeta style="width: 40%">
- <template #title>{{ item.alertName }}</template>
- <template #avatar>
- <div class="avatar">
- <SvgIcon name="flink" />
- </div>
- </template>
- </ListItemMeta>
- <div class="list-content" style="width: 40%">
- <div text-align center>Alert Type</div>
- <SvgIcon name="mail" size="25"
v-if="computeAlertType(item.alertType).indexOf(1) > -1" />
- <SvgIcon
- name="dingtalk"
- size="25"
- v-if="computeAlertType(item.alertType).indexOf(2) > -1"
- />
- <SvgIcon name="wecom" size="25"
v-if="computeAlertType(item.alertType).indexOf(4) > -1" />
- <SvgIcon name="message" size="25"
v-if="computeAlertType(item.alertType).indexOf(8) > -1" />
- <SvgIcon name="lark" size="25"
v-if="computeAlertType(item.alertType).indexOf(16) > -1" />
- </div>
- <template #actions>
- <Tooltip title="Alert Test">
- <a-button
- @click="handleTestAlarm(item)"
- type="link"
- size="large"
- style="margin-left: 3px"
- class="control-button ctl-btn-color"
- >
- <ThunderboltOutlined />
- </a-button>
- </Tooltip>
- <Tooltip title="Edit Alert Config">
- <a-button
- @click="handleEditAlertConf(item)"
- type="link"
- size="large"
- style="margin-left: 3px"
- class="control-button ctl-btn-color"
- >
- <EditOutlined />
- </a-button>
- </Tooltip>
- <Popconfirm
- :title="t('flink.setting.alert.delete')"
- :cancel-text="t('common.no')"
- :ok-text="t('common.yes')"
- @confirm="handleDeleteAlertConf(item)"
+
+ <List
+ class="alert-card-list"
+ :grid="{ gutter: 40, lg: 2, xxl: 3 }"
+ :data-source="alerts"
+ :pagination="false"
+ >
+ <template #renderItem="{ item }">
+ <ListItem>
+ <Card
+ class="shadow-xl alert-card"
+ :bordered="false"
+ :bodyStyle="{ height: '260px', padding: '15px', overflowY: 'auto' }"
>
- <a-button type="link" size="large" style="margin-left: 3px"
class="control-button">
- <DeleteOutlined style="color: red" />
- </a-button>
- </Popconfirm>
- </template>
- </ListItem>
+ <template #title>
+ {{ item.alertName }}
+ <div class="tag-list mt-4px">
+ <Tag
+ color="blue"
+ size="small"
+ v-for="type in item.alertTypeTags"
+ :key="type"
+ class="!leading-15px"
+ >
+ {{ getAlertTypeName(type) }}
+ </Tag>
+ </div>
+ </template>
+ <template #actions>
+ <Tooltip title="Alert Test">
+ <a-button
+ @click="handleTestAlarm(item)"
+ shape="circle"
+ size="large"
+ style="margin-left: 3px"
+ class="control-button ctl-btn-color"
+ >
+ <ThunderboltOutlined />
+ </a-button>
+ </Tooltip>
+ <Tooltip title="Edit Alert Config">
+ <a-button
+ @click="handleEditAlertConf(item)"
+ shape="circle"
+ size="large"
+ style="margin-left: 3px"
+ class="control-button ctl-btn-color"
+ >
+ <EditOutlined />
+ </a-button>
+ </Tooltip>
+ <Popconfirm
+ :title="t('flink.setting.alert.delete')"
+ :cancel-text="t('common.no')"
+ :ok-text="t('common.yes')"
+ @confirm="handleDeleteAlertConf(item)"
+ >
+ <a-button
+ type="danger"
+ shape="circle"
+ size="large"
+ style="margin-left: 3px"
+ class="control-button"
+ >
+ <DeleteOutlined />
+ </a-button>
+ </Popconfirm>
+ </template>
+
+ <AlertTypeInfo
+ alertType="1"
+ :alertSource="item"
+ v-if="item.alertTypeTags.includes('1')"
+ />
+ <AlertTypeInfo
+ alertType="2"
+ :alertSource="item"
+ v-if="item.alertTypeTags.includes('2')"
+ />
+ <AlertTypeInfo
+ alertType="4"
+ :alertSource="item"
+ v-if="item.alertTypeTags.includes('4')"
+ />
+ <AlertTypeInfo
+ alertType="8"
+ :alertSource="item"
+ v-if="item.alertTypeTags.includes('8')"
+ />
+ <AlertTypeInfo
+ alertType="16"
+ :alertSource="item"
+ v-if="item.alertTypeTags.includes('16')"
+ />
+ </Card>
+ </ListItem>
+ </template>
</List>
+
<AlertModal @register="registerAlertModal" @reload="getAlertSetting"
width="850px" />
</template>
+<style lang="less">
+ .alert-card {
+ .ant-card-head-title {
+ padding: 8px 0;
+ }
+ }
+ .alert-card-list {
+ .ant-list-empty-text {
+ background-color: white;
+ }
+ }
+</style>
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertTypeInfo.vue
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertTypeInfo.vue
new file mode 100644
index 000000000..5899f470b
--- /dev/null
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/AlertTypeInfo.vue
@@ -0,0 +1,119 @@
+<!--
+ 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.
+-->
+
+<script setup lang="ts">
+ import { Descriptions, Tag } from 'ant-design-vue';
+ import { computed, toRefs } from 'vue';
+ import { SvgIcon } from '/@/components/Icon';
+ import { BasicTitle } from '/@/components/Basic';
+ import { alertTypes } from './alert.data';
+ const props = defineProps({
+ alertType: {
+ type: String,
+ validator: (v: string) => ['1', '2', '4', '8', '16'].includes(v),
+ required: true,
+ },
+ alertSource: {
+ type: Object as PropType<Recordable>,
+ required: true,
+ },
+ });
+ const { alertType, alertSource } = toRefs(props);
+ const DescriptionsItem = Descriptions.Item;
+
+ const emailInfo = computed(() => {
+ return JSON.parse(alertSource.value.emailParams || '{}');
+ });
+ const dingTalk = computed(() => {
+ return JSON.parse(alertSource.value.dingTalkParams || '{}');
+ });
+ const weChat = computed(() => {
+ return JSON.parse(alertSource.value.weComParams || '{}');
+ });
+ const lark = computed(() => {
+ return JSON.parse(alertSource.value.larkParams || '{}');
+ });
+ function desensitization(dataString: string) {
+ return String(dataString).replace(/^(.{4})(?:.+)(.{4})$/,
'\$1********\$2');
+ }
+</script>
+
+<template>
+ <BasicTitle class="mt-10px border-dot">
+ <div class="flex items-center">
+ <SvgIcon :name="alertTypes[alertType].icon" :size="20"
class="!align-middle" />
+ <span class="pl-10px">
+ {{ alertTypes[alertType].name }}
+ </span>
+ </div>
+ </BasicTitle>
+ <Descriptions size="small" :column="2" class="pl-15px mt-10px">
+ <template v-if="alertType === '1'">
+ <DescriptionsItem label="Alert Email" :span="2">
+ <span class="text-blue-500">{{ emailInfo.contacts || '' }}</span>
+ </DescriptionsItem>
+ </template>
+ <template v-else-if="alertType === '2'">
+ <DescriptionsItem label="DingTalk Url" :span="2">
+ {{ dingTalk.alertDingURL || '' }}
+ </DescriptionsItem>
+ <DescriptionsItem label="Access Token" :span="2">
+ {{ desensitization(dingTalk.token || '') }}
+ </DescriptionsItem>
+ <DescriptionsItem label="Secret Token" v-if="dingTalk.secretToken"
:span="2">
+ {{ desensitization(dingTalk.secretToken || '') }}
+ </DescriptionsItem>
+ <DescriptionsItem label="DingTalk User">
+ {{ dingTalk.contacts || '' }}
+ </DescriptionsItem>
+ <DescriptionsItem label="At All User">
+ <Tag :color="dingTalk.isAtAll ? 'green' : 'red'" class="!leading-20px">
+ {{ dingTalk.isAtAll }}
+ </Tag>
+ </DescriptionsItem>
+ </template>
+ <template v-else-if="alertType === '4'">
+ <DescriptionsItem label="WeChat token" :span="2">
+ {{ desensitization(weChat.token || '') }}
+ </DescriptionsItem>
+ </template>
+ <template v-else-if="alertType === '16'">
+ <DescriptionsItem label="Lark Token" :span="2">
+ {{ desensitization(lark.token || '') }}
+ </DescriptionsItem>
+ <DescriptionsItem label="Lark Secret Token" :span="2">
+ {{ desensitization(lark.secretToken || '') }}
+ </DescriptionsItem>
+ <DescriptionsItem label="At All User">
+ <Tag :color="lark.isAtAll ? 'green' : 'red'" class="!leading-20px">
+ {{ lark.isAtAll }}
+ </Tag>
+ </DescriptionsItem>
+ </template>
+ </Descriptions>
+</template>
+<style lang="less">
+ .border-dot:before {
+ content: '';
+ width: 0;
+ height: 20px;
+ margin-top: 2px;
+ border: 2px solid #24c6dc;
+ border-radius: 2px;
+ transform: translateX(-10px);
+ }
+</style>
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/SettingList.vue
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/SettingList.vue
index 51426f76a..b9fa1218b 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/SettingList.vue
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/SettingList.vue
@@ -44,6 +44,7 @@
'alert.email.password': 'keys',
'alert.email.ssl': 'ssl',
'streampark.console.webapp.address': 'http',
+ 'ingress.mode.default': 'settings',
};
const ListItem = List.Item;
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/SystemSetting.vue
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/SystemSetting.vue
index bb9b86f3f..3d99bf080 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/SystemSetting.vue
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/SystemSetting.vue
@@ -34,24 +34,27 @@
const settings = ref<SystemSetting[]>([]);
const settingsList = computed(() => {
+ const filterValue = (key: string) => {
+ return settings.value.filter((i) => i.settingKey.indexOf(key) > -1);
+ };
return [
{
key: 1,
title: 'Maven Setting',
- isPassword: (item) => item.settingKey ===
'streampark.maven.auth.password',
- data: settings.value.filter((i) =>
i.settingKey.indexOf('streampark.maven') > -1),
+ isPassword: (item: SystemSetting) => item.settingKey ===
'streampark.maven.auth.password',
+ data: filterValue('streampark.maven'),
},
{
key: 2,
title: 'Docker Setting',
- isPassword: (item) => item.settingKey === 'docker.register.password',
- data: settings.value.filter((i) =>
i.settingKey.indexOf('docker.register') > -1),
+ isPassword: (item: SystemSetting) => item.settingKey ===
'docker.register.password',
+ data: filterValue('docker.register'),
},
{
key: 3,
title: 'Sender Email Setting',
- isPassword: (item) => item.settingKey === 'alert.email.password',
- data: settings.value.filter((i) => i.settingKey.indexOf('alert.email')
> -1),
+ isPassword: (item: SystemSetting) => item.settingKey ===
'alert.email.password',
+ data: filterValue('alert.email'),
},
{
key: 4,
@@ -63,7 +66,7 @@
key: 5,
title: 'Ingrsss Setting',
isPassword: () => false,
- data: settings.value.filter((i) => i.settingKey.indexOf('ingrsss') >
-1),
+ data: filterValue('ingrsss.mode'),
},
];
});
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/alert.data.ts
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/alert.data.ts
index 0c7662b8f..b4f1633e9 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/components/alert.data.ts
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/components/alert.data.ts
@@ -22,47 +22,70 @@ export const alertFormSchema: Array<FormSchema> = [
label: 'Fault Alert Type',
component: 'Select',
slot: 'type',
- dynamicRules: () => {
- return [{ required: true, message: 'Fault Alert Type is required' }];
- },
+ dynamicRules: () => [{ required: true, message: 'Fault Alert Type is
required' }],
+ },
+ {
+ field: 'alertEmail',
+ label: 'Alert Email',
+ component: 'Input',
+ colSlot: 'alertEmail',
},
- { field: 'alertEmail', label: 'Alert Email', component: 'Input', colSlot:
'alertEmail' },
{
field: 'alertDingURL',
label: 'DingTalk Url',
component: 'Input',
colSlot: 'alertDingURL',
- defaultValue: 'https://oapi.dingtalk.com/robot/send',
},
{
field: 'dingtalkToken',
label: 'Access Token',
component: 'Input',
- colSlot: 'dingtalkToken',
+ componentProps: {
+ placeholder: 'Please enter the access token of DingTalk',
+ },
+ rules: [{ required: true, message: 'Access token is required' }],
+ ifShow: ({ model }) => (model.alertType || []).includes('2'),
},
{
field: 'dingtalkSecretEnable',
label: 'Secret Enable',
- component: 'Input',
- colSlot: 'dingtalkSecretEnable',
+ component: 'Switch',
+ componentProps: {
+ checkedChildren: 'ON',
+ unCheckedChildren: 'OFF',
+ },
+ helpMessage: 'DingTalk ecretToken is enable',
+ ifShow: ({ model }) => (model.alertType || []).includes('2'),
},
{
field: 'dingtalkSecretToken',
label: 'Secret Token',
component: 'Input',
- colSlot: 'dingtalkSecretToken',
+ componentProps: {
+ placeholder: 'please enter Secret Token',
+ },
+ ifShow: ({ model }) => (model.alertType || []).includes('2') &&
model.dingtalkSecretEnable,
+ rules: [{ required: true, message: 'DingTalk SecretToken is required',
trigger: 'blur' }],
},
{
field: 'alertDingUser',
label: 'DingTalk User',
component: 'Input',
- colSlot: 'alertDingUser',
+ componentProps: {
+ placeholder: 'Please enter DingTalk receive user',
+ },
+ ifShow: ({ model }) => (model.alertType || []).includes('2'),
},
{
field: 'dingtalkIsAtAll',
label: 'At All User',
- component: 'Input',
- colSlot: 'dingtalkIsAtAll',
+ component: 'Switch',
+ componentProps: {
+ checkedChildren: 'ON',
+ unCheckedChildren: 'OFF',
+ },
+ helpMessage: 'Whether Notify All',
+ ifShow: ({ model }) => (model.alertType || []).includes('2'),
},
{
field: 'weToken',
@@ -94,6 +117,7 @@ export const alertFormSchema: Array<FormSchema> = [
rows: 4,
placeholder: 'SMS Template is required',
},
+ ifShow: ({ model }) => (model.alertType || []).includes('8'),
colSlot: 'alertSmsTemplate',
},
{
@@ -101,23 +125,46 @@ export const alertFormSchema: Array<FormSchema> = [
label: 'Lark Token',
component: 'InputTextArea',
colSlot: 'larkToken',
+ rules: [{ required: true, message: 'Lark token is required' }],
},
{
field: 'larkIsAtAll',
label: 'At All User',
component: 'Switch',
- colSlot: 'larkIsAtAll',
+ componentProps: {
+ checkedChildren: 'ON',
+ unCheckedChildren: 'OFF',
+ },
+ ifShow: ({ model }) => (model.alertType || []).includes('16'),
+ helpMessage: 'Whether Notify All',
},
{
field: 'larkSecretEnable',
label: 'Secret Enable',
component: 'Switch',
- colSlot: 'larkSecretEnable',
+ componentProps: {
+ checkedChildren: 'ON',
+ unCheckedChildren: 'OFF',
+ },
+ helpMessage: 'Lark secretToken is enable',
+ ifShow: ({ model }) => (model.alertType || []).includes('16'),
},
{
field: 'larkSecretToken',
label: 'Lark Secret Token',
- component: 'Switch',
- colSlot: 'larkSecretToken',
+ component: 'Input',
+ componentProps: {
+ placeholder: 'please enter Lark Secret Token',
+ },
+ ifShow: ({ model }) => (model.alertType || []).includes('16') &&
model.larkSecretEnable,
+ rules: [{ required: true, message: 'Lark SecretToken is required',
trigger: 'blur' }],
},
];
+
+export const alertTypes = {
+ '1': { name: 'E-mail', value: 1, disabled: false, icon: 'mail' },
+ '2': { name: 'Ding Talk', value: 2, disabled: false, icon: 'dingtalk' },
+ '4': { name: 'Wechat', value: 4, disabled: false, icon: 'wecom' },
+ '8': { name: 'SMS', value: 8, disabled: true, icon: 'message' },
+ '16': { name: 'Lark', value: 16, disabled: false, icon: 'lark' },
+};
diff --git
a/streampark-console/streampark-console-newui/src/views/flink/setting/hooks/useClusterSetting.ts
b/streampark-console/streampark-console-newui/src/views/flink/setting/hooks/useClusterSetting.ts
index 25df0605e..d131f4867 100644
---
a/streampark-console/streampark-console-newui/src/views/flink/setting/hooks/useClusterSetting.ts
+++
b/streampark-console/streampark-console-newui/src/views/flink/setting/hooks/useClusterSetting.ts
@@ -17,7 +17,7 @@
import { RuleObject } from 'ant-design-vue/lib/form';
import { StoreValue } from 'ant-design-vue/lib/form/interface';
import { computed, onMounted, reactive, ref, unref } from 'vue';
-import { executionModes, k8sRestExposedType, resolveOrder } from
'../../app/data';
+import { k8sRestExposedType, resolveOrder } from '../../app/data';
import {
renderProperties,
renderInputDropdown,
@@ -102,7 +102,11 @@ export const useClusterSetting = () => {
component: 'Select',
componentProps: {
placeholder: 'Please enter cluster name',
- options: executionModes,
+ options: [
+ { label: 'remote (standalone)', value: 1 },
+ { label: 'yarn session', value: 3 },
+ { label: 'kubernetes session', value: 5 },
+ ],
},
dynamicRules: () => {
return [{ required: true, validator: handleCheckExecMode }];
diff --git
a/streampark-console/streampark-console-newui/src/views/system/variable/DependApps.vue
b/streampark-console/streampark-console-newui/src/views/system/variable/DependApps.vue
new file mode 100644
index 000000000..22bf4e5c5
--- /dev/null
+++
b/streampark-console/streampark-console-newui/src/views/system/variable/DependApps.vue
@@ -0,0 +1,70 @@
+<!--
+ 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.
+-->
+<script lang="ts">
+ export default {
+ name: 'DependApp',
+ };
+</script>
+<script setup lang="ts" name="DependApp">
+ import { ref } from 'vue';
+ import { useRoute, useRouter } from 'vue-router';
+ import { fetchDependApps } from '/@/api/system/variable';
+ import Icon from '/@/components/Icon';
+ import { PageWrapper } from '/@/components/Page';
+ import { BasicTable } from '/@/components/Table';
+
+ const route = useRoute();
+ const router = useRouter();
+ const tableConfig = ref({
+ api: fetchDependApps,
+ canResize: false,
+ showIndexColumn: false,
+ beforeFetch(params: Recordable) {
+ Object.assign(params, {
+ variableCode: route.query.id,
+ });
+ return params;
+ },
+ columns: [
+ { title: 'Application Name', dataIndex: 'jobName', width: 500 },
+ { title: 'Owner', dataIndex: 'nickName' },
+ { title: 'Create Time', dataIndex: 'createTime' },
+ ],
+ });
+</script>
+
+<template>
+ <PageWrapper content-full-height content-background contentClass="p-24px">
+ <div class="mb-15px">
+ <a-button type="primary" shape="circle" @click="router.back()"
class="mr-10px -mt-8px">
+ <Icon icon="ant-design:arrow-left-outlined" />
+ </a-button>
+ <span class="app-bar">Variable "{{ route.query.id }}" used list</span>
+ </div>
+ <BasicTable v-bind="tableConfig" />
+ </PageWrapper>
+</template>
+
+<style lang="less">
+ .app-bar {
+ background-color: @background-color-base;
+ height: 100%;
+ font-weight: normal;
+ margin: 0 32px 0 0;
+ padding: 8px 12px;
+ }
+</style>
diff --git
a/streampark-console/streampark-console-newui/src/views/system/variable/View.vue
b/streampark-console/streampark-console-newui/src/views/system/variable/View.vue
index d0be38577..90744f456 100644
---
a/streampark-console/streampark-console-newui/src/views/system/variable/View.vue
+++
b/streampark-console/streampark-console-newui/src/views/system/variable/View.vue
@@ -38,6 +38,12 @@
tooltip: 'view detail',
onClick: handleView.bind(null, record),
},
+ {
+ icon: 'icon-park-outline:mind-mapping',
+ tooltip: 'depend apps',
+ onClick: () =>
+ router.push('/system/variable/depend_apps?id=' +
record.variableCode),
+ },
{
icon: 'ant-design:delete-outlined',
color: 'error',
@@ -65,16 +71,18 @@
<script lang="ts" setup>
import { defineComponent } from 'vue';
- import { BasicTable, useTable, TableAction } from '/@/components/Table';
- import VariableDrawer from './VariableDrawer.vue';
- import VariableInfo from './VariableInfo.vue';
+ import { BasicTable, useTable, TableAction, SorterResult } from
'/@/components/Table';
+ import VariableDrawer from './components/VariableDrawer.vue';
+ import VariableInfo from './components/VariableInfo.vue';
import { useDrawer } from '/@/components/Drawer';
import { columns, searchFormSchema } from './variable.data';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import { fetchVariableDelete, fetchVariableList } from
'/@/api/system/variable';
import Icon from '/@/components/Icon';
+ import { useRouter } from 'vue-router';
+ const router = useRouter();
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerInfo, { openDrawer: openInfoDraw }] = useDrawer();
const { createMessage } = useMessage();
@@ -88,6 +96,19 @@
colon: true,
schemas: searchFormSchema,
},
+ sortFn: (sortInfo: SorterResult) => {
+ const { field, order } = sortInfo;
+ if (field && order) {
+ return {
+ // The sort field passed to the backend you
+ sortField: field,
+ // Sorting method passed to the background asc/desc
+ sortOrder: order === 'ascend' ? 'asc' : 'desc',
+ };
+ } else {
+ return {};
+ }
+ },
rowKey: 'id',
pagination: true,
useSearchForm: true,
diff --git
a/streampark-console/streampark-console-newui/src/views/system/variable/VariableDrawer.vue
b/streampark-console/streampark-console-newui/src/views/system/variable/components/VariableDrawer.vue
similarity index 99%
rename from
streampark-console/streampark-console-newui/src/views/system/variable/VariableDrawer.vue
rename to
streampark-console/streampark-console-newui/src/views/system/variable/components/VariableDrawer.vue
index ddfb27903..8a6f70b53 100644
---
a/streampark-console/streampark-console-newui/src/views/system/variable/VariableDrawer.vue
+++
b/streampark-console/streampark-console-newui/src/views/system/variable/components/VariableDrawer.vue
@@ -69,7 +69,6 @@
const { data } = await fetchCheckVariableCode({
variableCode: value,
});
- console.log('data', data);
if (data.status !== 'success') {
setValidateStatus('error');
setHelp(data.message);
diff --git
a/streampark-console/streampark-console-newui/src/views/system/variable/VariableInfo.vue
b/streampark-console/streampark-console-newui/src/views/system/variable/components/VariableInfo.vue
similarity index 100%
rename from
streampark-console/streampark-console-newui/src/views/system/variable/VariableInfo.vue
rename to
streampark-console/streampark-console-newui/src/views/system/variable/components/VariableInfo.vue