You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampark.apache.org by be...@apache.org on 2022/10/26 02:09:41 UTC

[incubator-streampark] branch dev updated: [Fix] page style and application bug (#1903)

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 21e0ddadc [Fix] page style and application bug (#1903)
21e0ddadc is described below

commit 21e0ddadc3fc763a1d771707dacc0154a32df316
Author: Sizhu Wang <39...@users.noreply.github.com>
AuthorDate: Wed Oct 26 10:09:34 2022 +0800

    [Fix] page style and application bug (#1903)
    
    * [Fix] page style and application bug
    
    * [Fix] search button loading status
    
    * [Header] add file header
---
 mvnw                                               |   0
 .../build/vite/plugin/theme.ts                     |   5 +-
 .../src/api/system/menu.ts                         |   6 +-
 .../src/api/system/user.ts                         |  14 ++
 .../components/Form/src/components/FormAction.vue  |   2 +
 .../src/components/Icon/src/IconPicker.vue         |   2 +-
 .../src/components/Menu/src/BasicMenu.vue          |   3 -
 .../src/components/Modal/src/index.less            |   1 +
 .../src/components/SimpleMenu/src/SimpleMenu.vue   |  10 +-
 .../Table/src/components/TableHeader.vue           |   2 +-
 .../src/design/ant/index.less                      |   9 ++
 .../src/design/ant/input.less                      |  20 +++
 .../streampark-console-newui/src/design/color.less |   3 +
 .../streampark-console-newui/src/design/index.less |   7 +
 .../src/design/nprogress.less                      |  83 +++++++++++
 .../streampark-console-newui/src/design/swal2.less | 100 +++++++++++++
 .../src/design/var/index.less                      |  16 +++
 .../src/hooks/web/useMessage.tsx                   |   6 +-
 .../src/router/constant.ts                         |  14 ++
 .../src/store/modules/user.ts                      |   2 +-
 .../src/utils/cache/persistent.ts                  |   4 +-
 .../src/views/base/login/Login.vue                 |   4 +-
 .../src/views/base/login/LoginForm.vue             |  89 +++++++++---
 .../src/views/base/login/useLogin.ts               |   4 +
 .../src/views/flink/app/View.vue                   | 154 +++++++++++----------
 .../flink/app/components/AppDetail/DetailTab.vue   |   1 +
 .../components/AppView/StartApplicationModal.vue   |  23 ++-
 .../components/AppView/StopApplicationModal.vue    |  19 ++-
 .../src/views/flink/app/components/Dependency.vue  |  11 +-
 .../src/views/flink/app/components/customForm.tsx  | 114 +++++++++++++++
 .../src/views/flink/app/data/detail.data.ts        |  95 +++----------
 .../src/views/flink/app/data/index.ts              |   2 +-
 .../src/views/flink/app/hooks/useApp.tsx           |  21 +--
 .../flink/app/hooks/useCreateAndEditSchema.ts      |   9 +-
 .../src/views/flink/app/hooks/useFlinkRender.tsx   |  98 +++----------
 .../src/views/flink/app/hooks/useFlinkSchema.ts    |   4 +-
 .../src/views/flink/app/styles/Detail.less         |   4 +-
 .../src/views/flink/app/styles/View.less           |   4 +
 .../src/views/flink/project/View.vue               |   6 +-
 .../views/flink/project/components/ListItem.vue    |  11 +-
 .../views/flink/project/components/LogModal.vue    |  15 +-
 .../src/views/flink/project/project.data.ts        |  45 ++----
 .../setting/components/FlinkClusterSetting.vue     |  28 ++--
 .../flink/setting/components/FlinkEnvSetting.vue   |   2 +-
 .../flink/setting/components/SystemSetting.vue     |   8 +-
 .../src/views/system/member/Member.vue             |   7 +-
 .../src/views/system/menu/Menu.vue                 |   8 +-
 .../src/views/system/menu/menu.data.ts             |   2 -
 .../src/views/system/role/Role.vue                 |   6 +-
 .../src/views/system/role/role.data.ts             |   4 +-
 .../src/views/system/team/Team.vue                 |   8 +-
 .../src/views/system/token/Token.vue               |  11 +-
 .../views/system/token/components/TokenDrawer.vue  |  80 +++++++++++
 .../src/views/system/user/User.vue                 |  11 +-
 .../views/system/user/components/UserDrawer.vue    |   8 +-
 .../src/views/system/user/components/UserModal.vue |   2 +-
 .../src/views/system/user/user.data.ts             |  41 ++----
 .../src/views/system/variable/View.vue             |   8 +-
 58 files changed, 847 insertions(+), 429 deletions(-)

diff --git a/mvnw b/mvnw
old mode 100644
new mode 100755
diff --git a/streampark-console/streampark-console-newui/build/vite/plugin/theme.ts b/streampark-console/streampark-console-newui/build/vite/plugin/theme.ts
index b7e1ff47f..fbd7dc396 100644
--- a/streampark-console/streampark-console-newui/build/vite/plugin/theme.ts
+++ b/streampark-console/streampark-console-newui/build/vite/plugin/theme.ts
@@ -97,8 +97,9 @@ export function configThemePlugin(isBuild: boolean): PluginOption[] {
         'alert-error-border-color': '#58181c',
         'alert-error-bg-color': '#2a1215',
         'alert-error-icon-color': '#a61d24',
-        'background-color-light': '#fafafa',
-        'background-color-base': '#e6f7ff',
+        'background-color-light': 'rgba(255,255,255,.04)',
+        'background-color-base': '#2a2a2a',
+        'modal-mask-bg': 'rgba(255,255,255, 0.45)',
       },
     }),
   ];
diff --git a/streampark-console/streampark-console-newui/src/api/system/menu.ts b/streampark-console/streampark-console-newui/src/api/system/menu.ts
index 73ee561fb..1cf5359a5 100644
--- a/streampark-console/streampark-console-newui/src/api/system/menu.ts
+++ b/streampark-console/streampark-console-newui/src/api/system/menu.ts
@@ -23,11 +23,11 @@ enum Api {
   UpdateMenu = '/menu/update',
 }
 
-export const getMenuRouter = () => {
-  return defHttp.post<getMenuListResultModel>({ url: Api.MenuRouter });
+export const getMenuRouter = (): Promise<getMenuListResultModel> => {
+  return defHttp.post({ url: Api.MenuRouter });
 };
 
-export function editMenu(data?): Promise<boolean | undefined> {
+export function editMenu(data?: Recordable): Promise<boolean | undefined> {
   return defHttp.put({ url: Api.UpdateMenu, data });
 }
 
diff --git a/streampark-console/streampark-console-newui/src/api/system/user.ts b/streampark-console/streampark-console-newui/src/api/system/user.ts
index acfe80472..48af5ab90 100644
--- a/streampark-console/streampark-console-newui/src/api/system/user.ts
+++ b/streampark-console/streampark-console-newui/src/api/system/user.ts
@@ -30,6 +30,7 @@ import { BasicTableParams } from '../model/baseModel';
 
 enum Api {
   Login = '/passport/signin',
+  LoginByLdap = '/passport/ldapSignin',
   Logout = '/passport/signout',
   GetUserInfo = '/getUserInfo',
   GetPermCode = '/getPermCode',
@@ -61,6 +62,19 @@ export function loginApi(
     { isReturnNativeResponse: true, errorMessageMode: mode },
   );
 }
+/**
+ * @description: user login api (ldap)
+ * @return {Promise<AxiosResponse<Result<LoginResultModel>>>}
+ */
+export function loginLadpApi(
+  data: LoginParams,
+  mode: ErrorMessageMode = 'modal',
+): Promise<AxiosResponse<Result<LoginResultModel>>> {
+  return defHttp.post(
+    { url: Api.LoginByLdap, data },
+    { isReturnNativeResponse: true, errorMessageMode: mode },
+  );
+}
 
 /**
  * @description: getUserInfo
diff --git a/streampark-console/streampark-console-newui/src/components/Form/src/components/FormAction.vue b/streampark-console/streampark-console-newui/src/components/Form/src/components/FormAction.vue
index 5ea539efd..4235b95d6 100644
--- a/streampark-console/streampark-console-newui/src/components/Form/src/components/FormAction.vue
+++ b/streampark-console/streampark-console-newui/src/components/Form/src/components/FormAction.vue
@@ -74,6 +74,8 @@
       FormItem: Form.Item,
       Button,
       BasicArrow,
+      // ClearOutlined,
+      // SearchOutlined,
       [Col.name]: Col,
     },
     props: {
diff --git a/streampark-console/streampark-console-newui/src/components/Icon/src/IconPicker.vue b/streampark-console/streampark-console-newui/src/components/Icon/src/IconPicker.vue
index d38fee375..60ceaf6d7 100644
--- a/streampark-console/streampark-console-newui/src/components/Icon/src/IconPicker.vue
+++ b/streampark-console/streampark-console-newui/src/components/Icon/src/IconPicker.vue
@@ -41,7 +41,7 @@
 
         <template #content>
           <div v-if="getPaginationList.length">
-            <ScrollContainer class="border border-solid border-t-0">
+            <ScrollContainer class="border border-solid border-transparent border-t-0">
               <ul class="flex flex-wrap px-2">
                 <li
                   v-for="icon in getPaginationList"
diff --git a/streampark-console/streampark-console-newui/src/components/Menu/src/BasicMenu.vue b/streampark-console/streampark-console-newui/src/components/Menu/src/BasicMenu.vue
index 995038692..36e7757c8 100644
--- a/streampark-console/streampark-console-newui/src/components/Menu/src/BasicMenu.vue
+++ b/streampark-console/streampark-console-newui/src/components/Menu/src/BasicMenu.vue
@@ -113,12 +113,10 @@
         }
         return inlineCollapseOptions;
       });
-
       listenerRouteChange((route) => {
         if (route.name === REDIRECT_NAME) return;
         handleMenuChange(route);
         currentActiveMenu.value = route.meta?.currentActiveMenu as string;
-
         if (unref(currentActiveMenu)) {
           menuState.selectedKeys = [unref(currentActiveMenu)];
           setOpenKeys(unref(currentActiveMenu));
@@ -132,7 +130,6 @@
             handleMenuChange();
           },
         );
-
       async function handleMenuClick({ key }) {
         const { beforeClickFn } = props;
         if (beforeClickFn && isFunction(beforeClickFn)) {
diff --git a/streampark-console/streampark-console-newui/src/components/Modal/src/index.less b/streampark-console/streampark-console-newui/src/components/Modal/src/index.less
index cc3e2f5c4..d0220950d 100644
--- a/streampark-console/streampark-console-newui/src/components/Modal/src/index.less
+++ b/streampark-console/streampark-console-newui/src/components/Modal/src/index.less
@@ -93,6 +93,7 @@
   &-confirm-body {
     .ant-modal-confirm-content {
       // color: #fff;
+      margin-top: 30px;
 
       > * {
         color: @text-color-help-dark;
diff --git a/streampark-console/streampark-console-newui/src/components/SimpleMenu/src/SimpleMenu.vue b/streampark-console/streampark-console-newui/src/components/SimpleMenu/src/SimpleMenu.vue
index c9050ebdd..1f73f8f48 100644
--- a/streampark-console/streampark-console-newui/src/components/SimpleMenu/src/SimpleMenu.vue
+++ b/streampark-console/streampark-console-newui/src/components/SimpleMenu/src/SimpleMenu.vue
@@ -43,7 +43,7 @@
   import SimpleSubMenu from './SimpleSubMenu.vue';
   import { listenerRouteChange } from '/@/logics/mitt/routeChange';
   import { propTypes } from '/@/utils/propTypes';
-  import { REDIRECT_NAME } from '/@/router/constant';
+  import { menuMap, REDIRECT_NAME } from '/@/router/constant';
   import { useRouter } from 'vue-router';
   import { isFunction, isUrl } from '/@/utils/is';
   import { openWindow } from '/@/utils';
@@ -93,7 +93,6 @@
         mixSider,
         collapse,
       );
-
       const getBindValues = computed(() => ({ ...attrs, ...props }));
 
       watch(
@@ -137,8 +136,11 @@
           return;
         }
         const path = (route || unref(currentRoute)).path;
-
-        menuState.activeName = path;
+        if (Reflect.has(menuMap, path)) {
+          menuState.activeName = menuMap[path];
+        } else {
+          menuState.activeName = path;
+        }
 
         setOpenKeys(path);
       }
diff --git a/streampark-console/streampark-console-newui/src/components/Table/src/components/TableHeader.vue b/streampark-console/streampark-console-newui/src/components/Table/src/components/TableHeader.vue
index a7e00821a..dcc011c7c 100644
--- a/streampark-console/streampark-console-newui/src/components/Table/src/components/TableHeader.vue
+++ b/streampark-console/streampark-console-newui/src/components/Table/src/components/TableHeader.vue
@@ -27,13 +27,13 @@
         v-if="!$slots.tableTitle && title"
       />
       <div :class="`${prefixCls}__toolbar`">
-        <slot name="toolbar"></slot>
         <Divider type="vertical" v-if="$slots.toolbar && showTableSetting" />
         <TableSetting
           :setting="tableSetting"
           v-if="showTableSetting"
           @columns-change="handleColumnChange"
         />
+        <slot name="toolbar"></slot>
       </div>
     </div>
   </div>
diff --git a/streampark-console/streampark-console-newui/src/design/ant/index.less b/streampark-console/streampark-console-newui/src/design/ant/index.less
index bdaad131a..5dd4d1224 100644
--- a/streampark-console/streampark-console-newui/src/design/ant/index.less
+++ b/streampark-console/streampark-console-newui/src/design/ant/index.less
@@ -73,3 +73,12 @@ span.anticon:not(.app-iconify) {
   border-top: 0 !important;
   border-left: 0 !important;
 }
+
+// =================================
+// ==============modal message======
+// =================================
+[data-theme="dark"] {
+  .ant-descriptions-bordered .ant-descriptions-item-label {
+    background-color: transparent !important;
+  }
+}
diff --git a/streampark-console/streampark-console-newui/src/design/ant/input.less b/streampark-console/streampark-console-newui/src/design/ant/input.less
index a2d72567d..12ce09853 100644
--- a/streampark-console/streampark-console-newui/src/design/ant/input.less
+++ b/streampark-console/streampark-console-newui/src/design/ant/input.less
@@ -38,3 +38,23 @@
     padding: 4px;
   }
 }
+
+[data-theme="dark"] {
+
+  .ant-input-group.ant-input-group-compact > * {
+    border-right-color: transparent;
+  }
+
+  .ant-input-group-addon {
+    background-color: transparent !important;
+  }
+
+  .ant-picker-input > input[disabled],
+  .ant-input[disabled] {
+    color: #939393 !important;
+  }
+
+  .ant-picker-input > input:not(:focus) {
+    border-color: transparent !important;
+  }
+}
diff --git a/streampark-console/streampark-console-newui/src/design/color.less b/streampark-console/streampark-console-newui/src/design/color.less
index 849e1259d..2410e1561 100644
--- a/streampark-console/streampark-console-newui/src/design/color.less
+++ b/streampark-console/streampark-console-newui/src/design/color.less
@@ -152,3 +152,6 @@ html {
 @button-cancel-hover-color: @primary-color;
 @button-cancel-hover-bg-color: @white;
 @button-cancel-hover-border-color: @primary-color;
+
+// Modal
+@modal-mask-bg: fade(@black, 45%);
diff --git a/streampark-console/streampark-console-newui/src/design/index.less b/streampark-console/streampark-console-newui/src/design/index.less
index 95361e1fb..8ad3862aa 100644
--- a/streampark-console/streampark-console-newui/src/design/index.less
+++ b/streampark-console/streampark-console-newui/src/design/index.less
@@ -19,11 +19,18 @@
 @import 'public.less';
 @import 'ant/index.less';
 @import './theme.less';
+@import "./nprogress.less";
+@import "./swal2.less";
 
 input:-webkit-autofill {
   box-shadow: 0 0 0 1000px white inset !important;
 }
 
+[data-theme="dark"] input:-webkit-autofill {
+  box-shadow: none !important;
+  -webkit-text-fill-color: #fff;
+}
+
 :-webkit-autofill {
   transition: background-color 5000s ease-in-out 0s !important;
 }
diff --git a/streampark-console/streampark-console-newui/src/design/nprogress.less b/streampark-console/streampark-console-newui/src/design/nprogress.less
new file mode 100644
index 000000000..ce3169cdb
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/design/nprogress.less
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+/* Make clicks pass-through */
+#nprogress {
+  pointer-events: none;
+}
+
+#nprogress .bar {
+  background: @primary-color;
+  position: fixed;
+  z-index: 1031;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 2px;
+}
+
+/* Fancy blur effect */
+#nprogress .peg {
+  display: block;
+  position: absolute;
+  right: 0;
+  width: 100px;
+  height: 100%;
+  box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color;
+  opacity: 1;
+  transform: rotate(3deg) translate(0, -4px);
+}
+
+/* Remove these to get rid of the spinner */
+#nprogress .spinner {
+  display: block;
+  position: fixed;
+  z-index: 1031;
+  top: 15px;
+  right: 15px;
+}
+
+#nprogress .spinner-icon {
+  width: 18px;
+  height: 18px;
+  box-sizing: border-box;
+  border: solid 2px transparent;
+  border-top-color: @primary-color;
+  border-left-color: @primary-color;
+  border-radius: 50%;
+  animation: nprogress-spinner 400ms linear infinite;
+}
+
+.nprogress-custom-parent {
+  overflow: hidden;
+  position: relative;
+}
+
+.nprogress-custom-parent #nprogress .spinner,
+.nprogress-custom-parent #nprogress .bar {
+  position: absolute;
+}
+
+@keyframes nprogress-spinner {
+  0% {
+    transform: rotate(0deg);
+  }
+
+  100% {
+    transform: rotate(360deg);
+  }
+}
diff --git a/streampark-console/streampark-console-newui/src/design/swal2.less b/streampark-console/streampark-console-newui/src/design/swal2.less
new file mode 100644
index 000000000..b9154920f
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/design/swal2.less
@@ -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.
+ */
+[data-theme="dark"] {
+
+  .swal2-popup.swal2-toast {
+    background: #19191a;
+  }
+
+  .swal2-container.swal2-backdrop-show,
+  .swal2-container.swal2-noanimation {
+    background: hsl(0deg 0% 100% / 40%) !important;
+  }
+
+  .swal2-popup {
+    background: #19191a;
+  }
+
+  .swal2-title {
+    color: #e1e1e1;
+  }
+
+  .swal2-styled.swal2-default-outline:focus {
+    box-shadow: 0 0 0 1px #19191a, 0 0 0 3px hsl(210deg 47% 69% / 50%);
+  }
+
+  .swal2-footer {
+    border-top: 1px solid #555;
+    color: #bbb;
+  }
+
+  .swal2-timer-progress-bar {
+    background: hsl(0deg 0% 88% / 60%);
+  }
+
+  .swal2-html-container {
+    color: #e1e1e1;
+  }
+
+  .swal2-input,
+  .swal2-file,
+  .swal2-textarea {
+    background: #323234;
+    color: #e1e1e1;
+  }
+
+  .swal2-range {
+    background: #19191a;
+  }
+
+  .swal2-range output {
+    color: #e1e1e1;
+  }
+
+  .swal2-file {
+    background: #323234;
+  }
+
+  .swal2-select {
+    background: #323234;
+    color: #e1e1e1;
+  }
+
+  .swal2-radio,
+  .swal2-checkbox {
+    background: #19191a;
+    color: #e1e1e1;
+  }
+
+  .swal2-validation-message {
+    background: #323234;
+    color: #e1e1e1;
+  }
+
+  .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step ~ .swal2-progress-step {
+    background: #58585b;
+    color: #fff;
+  }
+
+  .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step ~ .swal2-progress-step-line {
+    background: #58585b;
+  }
+
+  body.swal2-no-backdrop .swal2-container .swal2-modal {
+    box-shadow: 0 0 10px hsl(240deg 2% 10% / 75%);
+  }
+}
diff --git a/streampark-console/streampark-console-newui/src/design/var/index.less b/streampark-console/streampark-console-newui/src/design/var/index.less
index d14f45ca2..e4c2a9203 100644
--- a/streampark-console/streampark-console-newui/src/design/var/index.less
+++ b/streampark-console/streampark-console-newui/src/design/var/index.less
@@ -53,3 +53,19 @@
     @content();
   }
 }
+
+@background-color-base: #e6f7ff;
+
+@gray-1: #ffffff;
+@gray-2: #fafafa;
+@gray-3: #f5f5f5;
+@gray-4: #f0f0f0;
+@gray-5: #d9d9d9;
+@gray-6: #bfbfbf;
+@gray-7: #8c8c8c;
+@gray-8: #595959;
+@gray-9: #434343;
+@gray-10: #262626;
+@gray-11: #1f1f1f;
+@gray-12: #141414;
+@gray-13: #000000;
diff --git a/streampark-console/streampark-console-newui/src/hooks/web/useMessage.tsx b/streampark-console/streampark-console-newui/src/hooks/web/useMessage.tsx
index 8dd94299e..6557dbb4a 100644
--- a/streampark-console/streampark-console-newui/src/hooks/web/useMessage.tsx
+++ b/streampark-console/streampark-console-newui/src/hooks/web/useMessage.tsx
@@ -23,6 +23,7 @@ import { NotificationArgsProps, ConfigProps } from 'ant-design-vue/lib/notificat
 import { useI18n } from './useI18n';
 import { isString } from '/@/utils/is';
 import Swal from 'sweetalert2';
+import 'sweetalert2/dist/sweetalert2.min.css';
 
 export interface NotifyApi {
   info(config: NotificationArgsProps): void;
@@ -39,7 +40,7 @@ export interface NotifyApi {
 export declare type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
 export declare type IconType = 'success' | 'info' | 'error' | 'warning';
 export interface ModalOptionsEx extends Omit<ModalFuncProps, 'iconType'> {
-  iconType: 'warning' | 'success' | 'error' | 'info';
+  iconType?: 'warning' | 'success' | 'error' | 'info';
 }
 export type ModalOptionsPartial = Partial<ModalOptionsEx> & Pick<ModalOptionsEx, 'content'>;
 
@@ -76,10 +77,11 @@ function renderContent({ content }: Pick<ModalOptionsEx, 'content'>) {
  */
 function createConfirm(options: ModalOptionsEx): ConfirmOptions {
   const iconType = options.iconType || 'warning';
+  const showIcon = options.iconType;
   Reflect.deleteProperty(options, 'iconType');
   const opt: ModalFuncProps = {
     centered: true,
-    icon: getIcon(iconType),
+    icon: showIcon ? getIcon(iconType) : false,
     ...options,
     content: renderContent(options),
   };
diff --git a/streampark-console/streampark-console-newui/src/router/constant.ts b/streampark-console/streampark-console-newui/src/router/constant.ts
index aea165413..b92c90f8a 100644
--- a/streampark-console/streampark-console-newui/src/router/constant.ts
+++ b/streampark-console/streampark-console-newui/src/router/constant.ts
@@ -38,3 +38,17 @@ export const getParentLayout = (_name?: string) => {
       });
     });
 };
+const projectPath = '/flink/project';
+const settingPath = '/flink/setting';
+const applicationPath = '/flink/app';
+export const menuMap = {
+  [`${projectPath}/add`]: projectPath,
+  [`${projectPath}/edit`]: projectPath,
+  [`${applicationPath}/add`]: applicationPath,
+  [`${applicationPath}/detail`]: applicationPath,
+  [`${applicationPath}/edit_flink`]: applicationPath,
+  [`${applicationPath}/edit_streampark`]: applicationPath,
+  [`${applicationPath}/edit_streampark`]: applicationPath,
+  [`${settingPath}/add_cluster`]: settingPath,
+  [`${settingPath}/edit_cluster`]: settingPath,
+};
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 a673f1bfa..48999bba4 100644
--- a/streampark-console/streampark-console-newui/src/store/modules/user.ts
+++ b/streampark-console/streampark-console-newui/src/store/modules/user.ts
@@ -138,7 +138,7 @@ export const useUserStore = defineStore({
       setAuthCache(PERMISSION_KEY, permissions);
     },
     setData(data: Recordable) {
-      const { token, expire, user, permissions, roles } = data;
+      const { token, expire, user, permissions, roles = [] } = data;
 
       this.setToken(token);
       this.setExpire(expire);
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 8635de947..8feb24cdb 100644
--- a/streampark-console/streampark-console-newui/src/utils/cache/persistent.ts
+++ b/streampark-console/streampark-console-newui/src/utils/cache/persistent.ts
@@ -34,7 +34,7 @@ import {
 } from '/@/enums/cacheEnum';
 import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting';
 import { toRaw } from 'vue';
-import { pick, omit } from 'lodash-es';
+import { pick, omit, debounce } from 'lodash-es';
 
 interface BasicStore {
   [TOKEN_KEY]: string | number | null | undefined;
@@ -147,6 +147,6 @@ function storageChange(e: any) {
   }
 }
 
-window.addEventListener('storage', storageChange);
+window.addEventListener('storage', debounce(storageChange, 500));
 
 initPersistentMemory();
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 730297d9d..5fcbfa4a8 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
@@ -87,6 +87,9 @@
     .@{prefix-cls} {
       background-color: @dark-bg;
 
+      .ant-input-affix-wrapper {
+        background-color: #232a3b !important;
+      }
       .ant-input,
       .ant-input-password {
         background-color: #232a3b;
@@ -107,7 +110,6 @@
 
     input.fix-auto-fill,
     .fix-auto-fill input {
-      -webkit-text-fill-color: #c9d1d9 !important;
       box-shadow: inherit !important;
     }
   }
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 b622ede49..9610dcc8f 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
@@ -68,9 +68,12 @@
 
     <FormItem class="enter-x">
       <Button type="primary" block @click="handleLogin" :loading="loading">
-        {{ t('sys.login.loginButton') }}
+        通过 {{ loginText.buttonText }} 登录
       </Button>
     </FormItem>
+    <FormItem class="enter-x text-center">
+      <Button type="link" @click="changeLoginType"> 使用 {{ loginText.linkText }} </Button>
+    </FormItem>
   </Form>
   <TeamModal v-model:visible="modelVisible" :userId="userId" @success="handleTeamSuccess" />
 </template>
@@ -85,57 +88,90 @@
   import { useMessage } from '/@/hooks/web/useMessage';
 
   import { useUserStore } from '/@/store/modules/user';
-  import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
+  import {
+    LoginStateEnum,
+    useLoginState,
+    useFormRules,
+    useFormValid,
+    LoginTypeEnum,
+  } from './useLogin';
   import { useDesign } from '/@/hooks/web/useDesign';
-  import { loginApi } from '/@/api/system/user';
+  import { loginApi, loginLadpApi } from '/@/api/system/user';
   import { APP_TEAMID_KEY_ } from '/@/enums/cacheEnum';
   import TeamModal from './teamModal.vue';
   import { fetchUserTeam } from '/@/api/system/member';
+  import { LoginResultModel } from '/@/api/system/model/userModel';
+  import { Result } from '/#/axios';
 
   const ACol = Col;
   const ARow = Row;
   const FormItem = Form.Item;
   const InputPassword = Input.Password;
+
   const { t } = useI18n();
   const { createErrorModal, createMessage } = useMessage();
   const { prefixCls } = useDesign('login');
   const userStore = useUserStore();
   const { setLoginState, getLoginState } = useLoginState();
   const { getFormRules } = useFormRules();
-
+  interface LoginForm {
+    account: string;
+    password: string;
+  }
   const formRef = ref();
   const loading = ref(false);
   const userId = ref('');
   const modelVisible = ref(false);
   const rememberMe = ref(false);
-
-  const formData = reactive({
+  const loginType = ref(LoginTypeEnum.LOCAL);
+  const formData = reactive<LoginForm>({
     account: '',
     password: '',
   });
 
+  const loginText = computed(() => {
+    const localText = '本地账户';
+    const ldapText = 'openLDAP';
+    if (loginType.value === LoginTypeEnum.LOCAL) {
+      return { buttonText: localText, linkText: ldapText };
+    }
+    return { buttonText: ldapText, linkText: localText };
+  });
+
   const { validForm } = useFormValid(formRef);
 
   const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
 
   async function handleLogin() {
-    const loginFormValue = await validForm();
-    if (!loginFormValue) return;
-    handleLoginAction(loginFormValue);
+    try {
+      const loginFormValue = await validForm();
+      if (!loginFormValue) return;
+      handleLoginAction(loginFormValue);
+    } catch (error) {
+      console.error(error);
+    }
+  }
+  async function handleLoginRequest(loginFormValue: LoginForm): Promise<Result<LoginResultModel>> {
+    // local login
+    if (loginType.value == LoginTypeEnum.LOCAL) {
+      const { data } = await loginApi(
+        { password: loginFormValue.password, username: loginFormValue.account },
+        'none',
+      );
+      return data;
+    }
+    const { data } = await loginLadpApi(
+      { password: loginFormValue.password, username: loginFormValue.account },
+      'none',
+    );
+    return data;
   }
-  async function handleLoginAction(loginFormValue: { password: string; account: string }) {
+  async function handleLoginAction(loginFormValue: LoginForm) {
     try {
       loading.value = true;
       try {
-        const { data } = await loginApi(
-          {
-            password: loginFormValue.password,
-            username: loginFormValue.account,
-          },
-          'none',
-        );
-
-        const { code } = data;
+        const { code, data } = await handleLoginRequest(loginFormValue);
+
         if (code != null && code != undefined) {
           if (code == 0 || code == 1) {
             const message =
@@ -144,7 +180,7 @@
             createMessage.error(message);
             return;
           } else if (code == 403) {
-            userId.value = data.data as unknown as string;
+            userId.value = data as unknown as string;
             const teamList = await fetchUserTeam({ userId: userId.value });
             userStore.setTeamList(teamList.map((i) => ({ label: i.teamName, value: i.id })));
 
@@ -154,10 +190,10 @@
             console.log(data);
           }
         }
-        userStore.setData(data.data);
+        userStore.setData(data);
         let successText = t('sys.login.loginSuccessDesc');
-        if (data.data?.user) {
-          const { teamId, nickName } = data.data.user;
+        if (data?.user) {
+          const { teamId, nickName } = data.user;
           userStore.teamId = teamId || '';
           sessionStorage.setItem(APP_TEAMID_KEY_, teamId || '');
           localStorage.setItem(APP_TEAMID_KEY_, teamId || '');
@@ -187,4 +223,11 @@
     modelVisible.value = false;
     handleLogin();
   }
+  function changeLoginType() {
+    if (loginType.value === LoginTypeEnum.LOCAL) {
+      loginType.value = LoginTypeEnum.LDAP;
+      return;
+    }
+    loginType.value = LoginTypeEnum.LOCAL;
+  }
 </script>
diff --git a/streampark-console/streampark-console-newui/src/views/base/login/useLogin.ts b/streampark-console/streampark-console-newui/src/views/base/login/useLogin.ts
index 305539491..115b73f49 100644
--- a/streampark-console/streampark-console-newui/src/views/base/login/useLogin.ts
+++ b/streampark-console/streampark-console-newui/src/views/base/login/useLogin.ts
@@ -25,6 +25,10 @@ export enum LoginStateEnum {
   MOBILE,
   QR_CODE,
 }
+export enum LoginTypeEnum {
+  LOCAL,
+  LDAP,
+}
 
 const currentState = ref(LoginStateEnum.LOGIN);
 
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/View.vue b/streampark-console/streampark-console-newui/src/views/flink/app/View.vue
index 7a865c4f3..2e5809072 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/View.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/View.vue
@@ -18,7 +18,6 @@
   import { defineComponent, onMounted, ref, reactive, unref, onUnmounted, watch } from 'vue';
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useUserStore } from '/@/store/modules/user';
-
   export default defineComponent({
     name: 'AppView',
   });
@@ -41,13 +40,15 @@
   import { handleIsStart, handleView } from './utils';
   import { useDrawer } from '/@/components/Drawer';
   import { useModal } from '/@/components/Modal';
-  import StatisticCard from './components/AppView/statisticCard.vue';
+
   import StartApplicationModal from './components/AppView/StartApplicationModal.vue';
   import StopApplicationModal from './components/AppView/StopApplicationModal.vue';
   import LogModal from './components/AppView/LogModal.vue';
   import BuildDrawer from './components/AppView/BuildDrawer.vue';
   import State from './components/State';
 
+  import StatisticCard from './components/AppView/statisticCard.vue';
+
   const SelectOption = Select.Option;
   const InputGroup = Input.Group;
   const InputSearch = Input.Search;
@@ -74,8 +75,9 @@
   const yarn = ref<Nullable<string>>(null);
 
   // Get Dashboard Metrics Data
-  async function handleDashboard() {
+  async function handleDashboard(showLoading: boolean) {
     try {
+      dashboardLoading.value = showLoading;
       const res = await fetchDashboard();
       if (res) {
         Object.assign(dashBigScreenMap, {
@@ -125,7 +127,6 @@
         delete params.state;
       }
       Object.assign(params, {
-        teamId: userStore.getTeamId,
         jobName: searchText.value,
         jobType: jobType.value,
         userId: userId.value,
@@ -172,12 +173,8 @@
     columns: getAppColumns(),
     showIndexColumn: false,
     showTableSetting: true,
-    tableSetting: { fullScreen: true },
-    actionColumn: {
-      dataIndex: 'operation',
-      title: 'Operation',
-      width: 180,
-    },
+    tableSetting: { fullScreen: true, redo: false },
+    actionColumn: { dataIndex: 'operation', title: 'Operation', width: 180 },
   });
 
   watch(
@@ -197,10 +194,6 @@
     openBuildDrawer(true, { appId: app.id });
   }
 
-  /* Click to add */
-  function handleAdd() {
-    router.push({ path: '/flink/app/add' });
-  }
   /* Click to edit */
   function handleEdit(app: AppListRecord) {
     flinkAppStore.setApplicationId(app.id);
@@ -220,8 +213,10 @@
 
   /* view */
   async function handleJobView(app: AppListRecord) {
+    console.log('app', app.state, app.optionState);
     // Task is running, restarting, in savePoint
     if ([4, 5].includes(app.state) || app['optionState'] === 4) {
+      console.log(app);
       // yarn-per-job|yarn-session|yarn-application
       handleView(app, unref(yarn));
     }
@@ -262,9 +257,7 @@
 
   function handleCancel(app: AppListRecord) {
     if (!optionApps.stopping.get(app.id) || app['optionState'] === 0) {
-      openStopModal(true, {
-        application: app,
-      });
+      openStopModal(true, { application: app });
     }
   }
   /* log view */
@@ -282,25 +275,20 @@
   } = useFlinkApplication(openStartModal);
 
   /*  tag */
-  async function handleInitTagsOptions() {
-    const params = Object.assign(
-      {},
-      {
-        pageSize: 999999999,
-        pageNum: 1,
-      },
-    );
-    const res = await fetchAppRecord(params);
-    const dataSource = res?.records || [];
-    dataSource.forEach((record) => {
-      if (record.tags !== null && record.tags !== undefined && record.tags !== '') {
-        const tagsArray = record.tags.split(',');
-        tagsArray.forEach((x) => {
-          if (x.length > 0 && tagsOptions.value.indexOf(x) == -1) {
-            tagsOptions.value.push(x);
-          }
-        });
-      }
+  function handleInitTagsOptions() {
+    const params = Object.assign({}, { pageSize: 999999999, pageNum: 1 });
+    fetchAppRecord(params).then((res) => {
+      const dataSource = res?.records || [];
+      dataSource.forEach((record) => {
+        if (record.tags !== null && record.tags !== undefined && record.tags !== '') {
+          const tagsArray = record.tags.split(',') as string[];
+          tagsArray.forEach((x: string) => {
+            if (x.length > 0 && tagsOptions.value.indexOf(x) == -1) {
+              tagsOptions.value.push(x);
+            }
+          });
+        }
+      });
     });
   }
 
@@ -409,8 +397,8 @@
   }
 
   const { start, stop } = useTimeoutFn(() => {
-    handleDashboard();
     if (!getLoading()) {
+      handleDashboard(false);
       reload({ polling: true });
     }
     start();
@@ -420,10 +408,16 @@
     stop();
   });
 
-  onMounted(async () => {
-    handleDashboard();
+  onMounted(() => {
+    handleDashboard(true);
     handleInitTagsOptions();
   });
+  watch(
+    () => [tags.value, userId.value, jobType.value],
+    () => {
+      reload({ polling: true });
+    },
+  );
 </script>
 <template>
   <PageWrapper contentFullHeight>
@@ -446,41 +440,55 @@
       <template #headerTop>
         <div class="text-right my-15px">
           <InputGroup compact>
-            <Select
-              placeholder="Tags"
-              show-search
-              allowClear
-              v-model:value="tags"
-              class="!ml-16px !w-150px text-left"
-            >
-              <SelectOption v-for="tag in tagsOptions" :key="tag">{{ tag }}</SelectOption>
-            </Select>
-            <Select
-              placeholder="Owner"
-              allowClear
-              v-model:value="userId"
-              class="!ml-16px !w-120px text-left"
-            >
-              <SelectOption v-for="u in users" :key="u.userId">
-                <span v-if="u.nickName"> {{ u.nickName }} </span>
-                <span v-else> {{ u.username }} </span>
-              </SelectOption>
-            </Select>
-            <Select
-              placeholder="Type"
-              allowClear
-              v-model:value="jobType"
-              class="!ml-16px w-80px text-left"
+            <div class="pr-16px">
+              <Select
+                placeholder="Tags"
+                show-search
+                allowClear
+                v-model:value="tags"
+                class="!w-150px text-left"
+              >
+                <SelectOption v-for="tag in tagsOptions" :key="tag">{{ tag }}</SelectOption>
+              </Select>
+            </div>
+
+            <div class="pr-16px">
+              <Select
+                placeholder="Owner"
+                allowClear
+                v-model:value="userId"
+                class="!w-120px text-left"
+              >
+                <SelectOption v-for="u in users" :key="u.userId">
+                  <span v-if="u.nickName"> {{ u.nickName }} </span>
+                  <span v-else> {{ u.username }} </span>
+                </SelectOption>
+              </Select>
+            </div>
+            <div class="pr-16px">
+              <Select
+                placeholder="Type"
+                allowClear
+                v-model:value="jobType"
+                class="w-100px text-left"
+              >
+                <SelectOption value="1">JAR</SelectOption>
+                <SelectOption value="2">SQL</SelectOption>
+              </Select>
+            </div>
+            <div class="pr-16px">
+              <InputSearch
+                placeholder="Search..."
+                v-model:value="searchText"
+                @search="reload({ polling: true })"
+                class="!w-250px text-left"
+              />
+            </div>
+            <a-button
+              type="primary"
+              style="margin-left: 20px"
+              @click="router.push({ path: '/flink/app/add' })"
             >
-              <SelectOption value="1">JAR</SelectOption>
-              <SelectOption value="2">SQL</SelectOption>
-            </Select>
-            <InputSearch
-              placeholder="Search..."
-              v-model:value="searchText"
-              class="!w-250px text-left"
-            />
-            <a-button type="primary" style="margin-left: 20px" @click="handleAdd">
               <Icon icon="ant-design:plus-outlined" />
               {{ t('common.add') }}
             </a-button>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/AppDetail/DetailTab.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppDetail/DetailTab.vue
index 0f0c21115..325385fb3 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/AppDetail/DetailTab.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppDetail/DetailTab.vue
@@ -312,6 +312,7 @@
                     auth: 'app:detail',
                     shape: 'circle',
                     type: 'default',
+                    ifShow: !record.success,
                     icon: 'ant-design:eye-outlined',
                     onClick: handleException.bind(null, record),
                   },
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StartApplicationModal.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StartApplicationModal.vue
index 292d48e59..536af5c03 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StartApplicationModal.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StartApplicationModal.vue
@@ -24,6 +24,7 @@
   });
 </script>
 <script setup lang="ts" name="StartApplicationModal">
+  import { h } from 'vue';
   import { Select, Input } from 'ant-design-vue';
   import { BasicForm, useForm } from '/@/components/Form';
   import { SvgIcon, Icon } from '/@/components/Icon';
@@ -60,7 +61,7 @@
           unCheckedChildren: 'OFF',
         },
         defaultValue: false,
-        helpMessage: 'flame Graph support',
+        itemExtra: h('span', { class: 'conf-switch' }, 'flame Graph support'),
         ifShow: () => [5, 6].includes(receiveData.executionMode),
       },
       {
@@ -72,7 +73,11 @@
           unCheckedChildren: 'OFF',
         },
         defaultValue: true,
-        helpMessage: 'restore the application from savepoint or latest checkpoint',
+        itemExtra: h(
+          'span',
+          { class: 'conf-switch' },
+          'restore the application from savepoint or latest checkpoint',
+        ),
       },
       {
         field: 'startSavePoint',
@@ -81,7 +86,11 @@
           receiveData.historySavePoint && receiveData.historySavePoint.length > 0
             ? 'Select'
             : 'Input',
-        helpMessage: 'restore the application from savepoint or latest checkpoint',
+        itemExtra: h(
+          'span',
+          { class: 'conf-switch' },
+          'restore the application from savepoint or latest checkpoint',
+        ),
         slot: 'savepoint',
         ifShow: ({ values }) => values.startSavePointed && !receiveData.latestSavePoint,
         required: true,
@@ -94,7 +103,11 @@
           checkedChildren: 'ON',
           unCheckedChildren: 'OFF',
         },
-        helpMessage: 'restore the application from savepoint or latest checkpoint',
+        itemExtra: h(
+          'span',
+          { class: 'conf-switch' },
+          'restore the application from savepoint or latest checkpoint',
+        ),
         defaultValue: false,
         ifShow: ({ values }) => values.startSavePointed,
       },
@@ -118,7 +131,7 @@
         savePointed,
         savePoint: savePointPath,
         flameGraph: formValue.flameGraph || false,
-        allowNonRestored: formValue.allowNonRestoredState || false
+        allowNonRestored: formValue.allowNonRestoredState || false,
       });
       if (data.data) {
         Swal.fire({
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StopApplicationModal.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StopApplicationModal.vue
index 9b5b3c9bf..27f8f264d 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StopApplicationModal.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StopApplicationModal.vue
@@ -29,12 +29,12 @@
   import { useMessage } from '/@/hooks/web/useMessage';
   import { fetchCancel, fetchCheckSavepointPath, fetchVerifySchema } from '/@/api/flink/app/app';
   import { CancelParam } from '/@/api/flink/app/app.type';
-
+  import { h } from 'vue';
   const emit = defineEmits(['register', 'updateOption']);
   const app = reactive<Recordable>({});
 
   const { t } = useI18n();
-  const { createErrorSwal, Swal, createErrorModal } = useMessage();
+  const { createErrorSwal, Swal } = useMessage();
   const [registerModal, { closeModal }] = useModalInner((data) => {
     if (data) {
       Object.assign(app, data.application);
@@ -54,7 +54,7 @@
           unCheckedChildren: 'OFF',
         },
         defaultValue: true,
-        helpMessage: 'trigger savePoint before taking cancel',
+        itemExtra: h('span', { class: 'conf-switch' }, 'trigger savePoint before taking cancel'),
       },
       {
         field: 'customSavepoint',
@@ -64,7 +64,11 @@
           placeholder: 'Entry the custom savepoint path',
           allowClear: true,
         },
-        helpMessage: 'restore the application from savepoint or latest checkpoint',
+        itemExtra: h(
+          'span',
+          { class: 'conf-switch' },
+          'restore the application from savepoint or latest checkpoint',
+        ),
         ifShow: ({ values }) => !!values.stopSavePointed,
       },
       {
@@ -76,7 +80,7 @@
           unCheckedChildren: 'OFF',
         },
         defaultValue: false,
-        helpMessage: 'Send max watermark before stopped',
+        itemExtra: h('span', { class: 'conf-switch' }, 'Send max watermark before stopped'),
       },
     ],
     colon: true,
@@ -114,11 +118,6 @@
           if (data.data) {
             handleStopAction(stopReq);
           } else {
-            createErrorModal({
-              title: t('common.failed'),
-              content: data.message,
-            });
-
             createErrorSwal(data.message);
           }
         }
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue
index ba797a6cb..734fdfc2a 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue
@@ -166,6 +166,8 @@
       const formData = new FormData();
       formData.append('file', data.file);
       await fetchUpload(formData);
+      // eslint-disable-next-line vue/no-mutating-props
+      if (!props?.formModel?.historyjar) props.formModel.historyjar = {};
       Object.assign(props.formModel.historyjar, {
         [data.file.name]: data.file.name,
       });
@@ -201,7 +203,7 @@
 </script>
 
 <template>
-  <Tabs type="card" v-model:activeKey="activeTab">
+  <Tabs type="card" v-model:activeKey="activeTab" class="pom-card">
     <TabPane key="pom" tab="Maven pom">
       <div ref="pomBox" class="pom-box syntax-true" style="height: 300px"></div>
       <a-button type="primary" class="apply-pom" @click="handleApplyPom()">
@@ -230,3 +232,10 @@
     </TabPane>
   </Tabs>
 </template>
+<style lang="less">
+  .pom-card {
+    .ant-tabs-nav {
+      margin-bottom: 0 !important;
+    }
+  }
+</style>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/customForm.tsx b/streampark-console/streampark-console-newui/src/views/flink/app/components/customForm.tsx
new file mode 100644
index 000000000..b551b12ea
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/customForm.tsx
@@ -0,0 +1,114 @@
+/* 
+  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 } from 'vue';
+import type { PropType } from 'vue';
+import { Button, Form, Input, InputNumber, Tag, Select } from 'ant-design-vue';
+import Icon from '/@/components/Icon';
+interface PriceValue {
+  cpMaxFailureInterval: number;
+  cpFailureRateInterval: number;
+  cpFailureAction: string;
+}
+import { cpTriggerAction } from '../data';
+export default defineComponent({
+  props: {
+    value: { type: Object as PropType<PriceValue>, isRequired: true },
+  },
+  emits: ['updateValue'],
+  setup(props, { emit }) {
+    const formItemContext = Form.useInjectFormItemContext();
+    const triggerChange = (changedValue: Partial<PriceValue>) => {
+      emit('updateValue', { ...props.value, ...changedValue });
+      formItemContext.onFieldChange();
+    };
+    const handleCpFailureRateIntervalChange = (value: any) => {
+      triggerChange({ cpFailureRateInterval: value });
+    };
+    const handleCpMaxFailureIntervalChange = (value: any) => {
+      // const newNumber = (e.target as any).value;
+      triggerChange({ cpMaxFailureInterval: value });
+    };
+    const handleFailureActionChange = (value: any) => {
+      triggerChange({ cpFailureAction: value });
+    };
+    return () => {
+      return (
+        <div>
+          <Input.Group compact class="!flex">
+            <InputNumber
+              min={1}
+              step={1}
+              name="cpMaxFailureInterval"
+              placeholder="checkpoint failure rate interval"
+              allow-clear
+              class="!w-260px mr-10px"
+              value={props.value?.cpMaxFailureInterval}
+              onChange={(value: any) => handleCpMaxFailureIntervalChange(value)}
+            />
+            <Button style="width: 70px"> minute </Button>
+            <InputNumber
+              style="margin-left: 1%"
+              name="cpFailureRateInterval"
+              min={1}
+              step={1}
+              placeholder="max failures per interval"
+              class="!mb-0 !w-200px"
+              value={props.value?.cpFailureRateInterval}
+              onChange={(value: any) => handleCpFailureRateIntervalChange(value)}
+            />
+
+            <Button style="width: 70px"> count </Button>
+            <Select
+              name="cpFailureAction"
+              style="margin-left: 1%"
+              placeholder="trigger action"
+              allow-clear
+              class="!mb-0 flex-1"
+              value={props.value?.cpFailureAction}
+              onChange={(e: any) => handleFailureActionChange(e)}
+            >
+              {cpTriggerAction.map((o) => {
+                return (
+                  <Select.Option key={o.value}>
+                    <Icon
+                      icon={
+                        o.value === 1 ? 'ant-design:alert-outlined' : 'ant-design:sync-outlined'
+                      }
+                    />
+                    {o.label}
+                  </Select.Option>
+                );
+              })}
+            </Select>
+          </Input.Group>
+          <p class="conf-desc mt-10px">
+            <span class="note-info">
+              <Tag color="#2db7f5" class="tag-note">
+                Note
+              </Tag>
+              Operation after checkpoint failure, e.g:
+              <br />
+              Within <span class="note-elem">5 minutes</span>(checkpoint failure rate interval), if
+              the number of checkpoint failures reaches <span class="note-elem">10</span> (max
+              failures per interval),action will be triggered(alert or restart job)
+            </span>
+          </p>
+        </div>
+      );
+    };
+  },
+});
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/data/detail.data.ts b/streampark-console/streampark-console-newui/src/views/flink/app/data/detail.data.ts
index 1376d7a95..8eb97bfb7 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/data/detail.data.ts
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/data/detail.data.ts
@@ -38,7 +38,7 @@ export const getDescSchema = (): DescItem[] => {
         h(
           'div',
           { class: 'app_state' },
-          h(Tag, { color: curVal === 1 ? '#545454' : '#0C7EF2' }, () =>
+          h(Tag, { color: curVal === 1 ? '#545454' : '#0C7EF2', class: 'mr-8px' }, () =>
             curVal === 1 ? 'Custom Code' : 'Flink SQL',
           ),
         ),
@@ -93,88 +93,29 @@ export const getDescSchema = (): DescItem[] => {
 };
 /* setting */
 export const getConfColumns = (): BasicColumn[] => [
-  {
-    title: 'Version',
-    dataIndex: 'version',
-  },
-  {
-    title: 'Conf Format',
-    dataIndex: 'format',
-  },
-  {
-    title: 'Effective',
-    dataIndex: 'effective',
-  },
-  {
-    title: 'Candidate',
-    dataIndex: 'candidate',
-  },
-  {
-    title: 'Modify Time',
-    dataIndex: 'createTime',
-  },
+  { title: 'Version', dataIndex: 'version' },
+  { title: 'Conf Format', dataIndex: 'format' },
+  { title: 'Effective', dataIndex: 'effective' },
+  { title: 'Candidate', dataIndex: 'candidate' },
+  { title: 'Modify Time', dataIndex: 'createTime' },
 ];
 
 export const getSavePointColumns = (): BasicColumn[] => [
-  {
-    title: 'Path',
-    dataIndex: 'path',
-    width: '45%',
-  },
-  {
-    title: 'Trigger Time',
-    dataIndex: 'triggerTime',
-    width: 250,
-  },
-  {
-    title: 'Type',
-    dataIndex: 'type',
-  },
-  {
-    title: 'Latest',
-    dataIndex: 'latest',
-  },
+  { title: 'Path', dataIndex: 'path', width: '45%' },
+  { title: 'Trigger Time', dataIndex: 'triggerTime', width: 250 },
+  { title: 'Type', dataIndex: 'type' },
+  { title: 'Latest', dataIndex: 'latest' },
 ];
 export const getBackupColumns = (): BasicColumn[] => [
-  {
-    title: 'Save Path',
-    dataIndex: 'path',
-    width: '40%',
-    align: 'left',
-  },
-  {
-    title: 'Description',
-    dataIndex: 'description',
-    width: '20%',
-  },
-  {
-    title: 'Version',
-    dataIndex: 'version',
-    width: '10%',
-  },
-  {
-    title: 'Backup Time',
-    dataIndex: 'createTime',
-  },
+  { title: 'Save Path', dataIndex: 'path', width: '40%', align: 'left' },
+  { title: 'Description', dataIndex: 'description', width: '20%' },
+  { title: 'Version', dataIndex: 'version', width: '10%' },
+  { title: 'Backup Time', dataIndex: 'createTime' },
 ];
 
 export const getOptionLogColumns = (): BasicColumn[] => [
-  {
-    title: 'Application Id',
-    dataIndex: 'yarnAppId',
-    width: '20%',
-  },
-  {
-    title: 'JobManager URL',
-    dataIndex: 'jobManagerUrl',
-    width: '25%',
-  },
-  {
-    title: 'Start Status',
-    dataIndex: 'success',
-  },
-  {
-    title: 'Option Time',
-    dataIndex: 'optionTime',
-  },
+  { title: 'Application Id', dataIndex: 'yarnAppId', width: '20%' },
+  { title: 'JobManager URL', dataIndex: 'jobManagerUrl', width: '25%' },
+  { title: 'Start Status', dataIndex: 'success' },
+  { title: 'Option Time', dataIndex: 'optionTime' },
 ];
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 422349476..17196c0ee 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
@@ -75,7 +75,7 @@ export const getAppColumns = (): BasicColumn[] => [
     title: 'Launch | Build',
     dataIndex: 'launch',
     width: 220,
-  }
+  },
 ];
 
 /* Get diff editor configuration */
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx
index 9a28a7ebd..19d62db69 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx
@@ -197,14 +197,16 @@ export const useFlinkApplication = (openStartModal: Fn) => {
     let copyAppName: string | undefined = '';
     createConfirm({
       width: '600px',
-      iconType: 'info',
       title: () => [
-        h(SvgIcon, { name: 'copy', style: { color: 'red', display: 'inline-block' } }),
+        h(SvgIcon, {
+          name: 'copy',
+          style: { color: 'red', display: 'inline-block', marginRight: '10px' },
+        }),
         'Copy Application',
       ],
       content: () => {
         return (
-          <Form>
+          <Form class="!pt-20px">
             <Form.Item
               label="Application Name"
               labelCol={{ lg: { span: 7 }, sm: { span: 7 } }}
@@ -266,9 +268,11 @@ export const useFlinkApplication = (openStartModal: Fn) => {
     const formValue = reactive<any>({});
     createConfirm({
       width: '600px',
-      iconType: 'info',
       title: () => [
-        h(SvgIcon, { name: 'mapping', style: { color: 'green', display: 'inline-block' } }),
+        h(SvgIcon, {
+          name: 'mapping',
+          style: { color: 'green', display: 'inline-block', marginRight: '10px' },
+        }),
         'Mapping Application',
       ],
       content: () => {
@@ -326,9 +330,10 @@ export const useFlinkApplication = (openStartModal: Fn) => {
     });
   }
 
-  onMounted(async () => {
-    const res = await fetchAppOwners({});
-    users.value = res;
+  onMounted(() => {
+    fetchAppOwners({}).then((res) => {
+      users.value = res;
+    });
   });
 
   return {
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useCreateAndEditSchema.ts b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useCreateAndEditSchema.ts
index 6462936f4..1fd185b05 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useCreateAndEditSchema.ts
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useCreateAndEditSchema.ts
@@ -381,7 +381,7 @@ export const useCreateAndEditSchema = (
         field: 'cpMaxFailureInterval',
         label: 'CheckPoint Failure Options',
         component: 'InputNumber',
-        render: ({ model }) => renderInputGroup(model),
+        renderColContent: ({ model }) => renderInputGroup(model),
         show: ({ values }) =>
           edit?.mode == 'flink' ? true : ![5, 6].includes(values.executionMode),
       },
@@ -507,8 +507,11 @@ export const useCreateAndEditSchema = (
               { type: 'info' },
               {
                 message: () => [
-                  h(Icon, { icon: 'ant-design:code-outlined', style: { color: '#108ee9' } }),
-                  h('span', { class: 'pl-5px' }, 'Custom Code'),
+                  h(Icon, {
+                    icon: 'ant-design:code-outlined',
+                    style: { color: '#108ee9' },
+                  }),
+                  h('span', { class: 'pl-8px' }, 'Custom Code'),
                 ],
               },
             );
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkRender.tsx b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkRender.tsx
index 247ddb5df..481274396 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkRender.tsx
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkRender.tsx
@@ -17,8 +17,9 @@
 import { RenderCallbackParams } from '/@/components/Form/src/types/form';
 import { Icon, SvgIcon } from '/@/components/Icon';
 import options from '../data/option';
-import { cpTriggerAction } from '../data';
+
 import Mergely from '../components/Mergely.vue';
+import CustomForm from '../components/customForm';
 import {
   Alert,
   Dropdown,
@@ -33,7 +34,7 @@ import {
 import { Button } from '/@/components/Button';
 import { descriptionFilter } from '../utils';
 import { SettingTwoTone } from '@ant-design/icons-vue';
-import { ref, unref } from 'vue';
+import { reactive, ref, unref } from 'vue';
 import { handleConfTemplate } from '/@/api/flink/config';
 import { decodeByBase64 } from '/@/utils/cipher';
 import { useMessage } from '/@/hooks/web/useMessage';
@@ -83,8 +84,9 @@ export const renderInputDropdown = (
   );
 };
 
-function handleCheckCheckpoint(values: Recordable) {
+export function handleCheckCheckpoint(values: Recordable) {
   const { cpMaxFailureInterval, cpFailureRateInterval, cpFailureAction } = values;
+  console.log('values', cpMaxFailureInterval, cpFailureRateInterval, cpFailureAction);
   if (cpMaxFailureInterval != null && cpFailureRateInterval != null && cpFailureAction != null) {
     if (cpFailureAction === 1) {
       const alertEmail = values.alertEmail;
@@ -114,80 +116,22 @@ function handleCheckCheckpoint(values: Recordable) {
 
 /* render input Group component */
 export const renderInputGroup = (model: Recordable) => {
+  const formValue = reactive({
+    cpMaxFailureInterval: model.cpMaxFailureInterval,
+    cpFailureRateInterval: model.cpFailureRateInterval,
+    cpFailureAction: model.cpFailureAction,
+  });
   return (
-    <div>
-      <Input.Group compact>
-        <Form.Item
-          name="cpMaxFailureInterval"
-          rules={{ trigger: 'blur', validator: () => handleCheckCheckpoint(model) }}
-        >
-          <InputNumber
-            min={1}
-            step={1}
-            placeholder="checkpoint failure rate interval"
-            allow-clear
-            class="!w-260px mr-10px"
-            value={model.cpMaxFailureInterval}
-            onInput={(value) => (model.cpMaxFailureInterval = value)}
-          />
-        </Form.Item>
-
-        <Button style="width: 70px"> minute </Button>
-        <Form.Item
-          name="cpFailureRateInterval"
-          rules={{ trigger: 'blur', validator: () => handleCheckCheckpoint(model) }}
-          style="margin-left: 1%"
-        >
-          <InputNumber
-            min={1}
-            step={1}
-            placeholder="max failures per interval"
-            class="!w-200px"
-            value={model.cpFailureRateInterval}
-            onInput={(value) => (model.cpFailureRateInterval = value)}
-          />
-        </Form.Item>
-
-        <Button style="width: 70px"> count </Button>
-        <Form.Item
-          name="cpFailureAction"
-          rules={{ trigger: 'change', validator: () => handleCheckCheckpoint(model) }}
-          style="margin-left: 1%"
-        >
-          <Select
-            placeholder="trigger action"
-            allow-clear
-            class="!w-170px"
-            value={model.cpFailureAction}
-            onChange={(value) => (model.cpFailureAction = value)}
-          >
-            {cpTriggerAction.map((o) => {
-              return (
-                <Select.Option key={o.value}>
-                  <Icon
-                    icon={o.value === 1 ? 'ant-design:alert-outlined' : 'ant-design:sync-outlined'}
-                  />
-                  {o.label}
-                </Select.Option>
-              );
-            })}
-          </Select>
-        </Form.Item>
-      </Input.Group>
-
-      <p class="conf-desc mt-10px">
-        <span class="note-info">
-          <Tag color="#2db7f5" class="tag-note">
-            Note
-          </Tag>
-          Operation after checkpoint failure, e.g:
-          <br />
-          Within <span class="note-elem">5 minutes</span>(checkpoint failure rate interval), if the
-          number of checkpoint failures reaches <span class="note-elem">10</span> (max failures per
-          interval),action will be triggered(alert or restart job)
-        </span>
-      </p>
-    </div>
+    <Form.Item
+      label="CheckPoint Failure Options"
+      name="CheckPointFailure"
+      rules={[{ validator: () => handleCheckCheckpoint(model) }]}
+    >
+      <CustomForm
+        value={formValue}
+        onUpdateValue={(value: any) => Object.assign(model, value)}
+      ></CustomForm>
+    </Form.Item>
   );
 };
 /*Gets the selection of totalOptions */
@@ -300,7 +244,7 @@ export const getAlertSvgIcon = (name: string, text: string) => {
       {{
         message: () => (
           <div>
-            <SvgIcon name={name} style={{ color: '#108ee9' }} />
+            <SvgIcon class="mr-8px" name={name} style={{ color: '#108ee9' }} />
             <span>{text}</span>
           </div>
         ),
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkSchema.ts b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkSchema.ts
index 6af44ae7c..10829e468 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkSchema.ts
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useFlinkSchema.ts
@@ -258,7 +258,7 @@ export const useFlinkSchema = (editModel?: string) => {
       field: 'cpMaxFailureInterval',
       label: 'CheckPoint Failure Options',
       component: 'InputNumber',
-      render: ({ model }) => renderInputGroup(model),
+      renderColContent: ({ model }) => renderInputGroup(model),
       show: ({ values }) => (editModel == 'flink' ? true : ![5, 6].includes(values.executionMode)),
     },
     {
@@ -378,7 +378,7 @@ export const useFlinkSchema = (editModel?: string) => {
               {
                 message: () => [
                   h(Icon, { icon: 'ant-design:code-outlined', style: { color: '#108ee9' } }),
-                  h('span', { class: 'pl-5px' }, 'Custom Code'),
+                  h('span', { class: 'pl-8px' }, 'Custom Code'),
                 ],
               },
             );
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/styles/Detail.less b/streampark-console/streampark-console-newui/src/views/flink/app/styles/Detail.less
index 0f1432309..6bc7c0bfb 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/styles/Detail.less
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/styles/Detail.less
@@ -25,7 +25,7 @@
 
 .ant-tabs-nav .ant-tabs-tab-active {
   font-weight: unset !important;
-  background-color: #e6f7ff;
+  background-color: @background-color-base;
 }
 
 .ant-tabs-nav .ant-tabs-tab {
@@ -33,7 +33,7 @@
 }
 
 .app-bar {
-  background-color: #e6f7ff;
+  background-color: @background-color-base;
   height: 100%;
   font-weight: normal;
   margin: 0 32px 0 0;
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/styles/View.less b/streampark-console/streampark-console-newui/src/views/flink/app/styles/View.less
index 719cbb633..ec23bd1bc 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/styles/View.less
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/styles/View.less
@@ -165,3 +165,7 @@
     box-shadow: 0 0 10px #3da9f2, inset 0 0 5px #3da9f2;
   }
 }
+
+[data-theme="dark"] .app_list .app_sql {
+  color: #f4f5f6;
+}
diff --git a/streampark-console/streampark-console-newui/src/views/flink/project/View.vue b/streampark-console/streampark-console-newui/src/views/flink/project/View.vue
index 778c5fea7..134528ea2 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/project/View.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/project/View.vue
@@ -27,7 +27,11 @@
             >{{ item.label }}</a-radio-button
           >
         </a-radio-group>
-        <a-input-search @search="handleSearch" class="search-input" />
+        <a-input-search
+          @search="handleSearch"
+          placeholder="please enter a keyword search"
+          class="search-input"
+        />
       </template>
     </a-card>
     <div class="operate pt-20px bg-white" v-auth="'project:create'">
diff --git a/streampark-console/streampark-console-newui/src/views/flink/project/components/ListItem.vue b/streampark-console/streampark-console-newui/src/views/flink/project/components/ListItem.vue
index f84a24e55..431f020e7 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/project/components/ListItem.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/project/components/ListItem.vue
@@ -19,7 +19,8 @@
   <a-list-item>
     <a-list-item-meta class="item-meta">
       <template #title>
-        <a>{{ item.name }}<a-badge status="processing" title="installing" v-if="isBuilding" /></a>
+        <a-badge status="processing" title="installing" class="mr-10px" v-if="isBuilding" />
+        <span>{{ item.name }}</span>
       </template>
       <template #description>
         <a-popover arrow-point-at-center trigger="hover" :content="item.url">
@@ -76,7 +77,7 @@
             ok-text="Yes"
             @confirm="handleBuild"
           >
-            <a-button type="link" size="large" class="ml-8px" v-auth="'project:build'">
+            <a-button shape="circle" size="large" class="ml-8px" v-auth="'project:build'">
               <ThunderboltOutlined />
             </a-button>
           </a-popconfirm>
@@ -88,7 +89,7 @@
           v-auth="'project:update'"
           size="large"
           @click="handleEdit"
-          type="link"
+          shape="circle"
           class="ml-8px"
         >
           <EditOutlined />
@@ -101,8 +102,8 @@
           ok-text="Yes"
           @confirm="handleDelete"
         >
-          <a-button type="link" size="large" style="margin-left: 8px">
-            <DeleteOutlined style="color: red" />
+          <a-button type="danger" shape="circle" size="large" style="margin-left: 8px">
+            <DeleteOutlined />
           </a-button>
         </a-popconfirm>
       </a-tooltip>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/project/components/LogModal.vue b/streampark-console/streampark-console-newui/src/views/flink/project/components/LogModal.vue
index 469e4a49c..e26fa957a 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/project/components/LogModal.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/project/components/LogModal.vue
@@ -35,12 +35,14 @@
   let startOffset: Nullable<number> = null;
   const logTime = ref<string>('');
   const getLogLoading = ref<boolean>(false);
+  const showRefresh = ref<boolean>(false);
   const project = reactive<Recordable>({});
   const [registerModal, { changeLoading, closeModal }] = useModalInner((data) => {
     data && onReceiveModalData(data);
   });
   const { setContent, logRef } = useLog();
-  function onReceiveModalData(data) {
+  function onReceiveModalData(data: Recordable) {
+    showRefresh.value = true;
     Object.assign(project, unref(data.project));
     changeLoading(true);
     refreshLog();
@@ -62,9 +64,12 @@
         startOffset,
       });
       if (data.readFinished === false) {
+        showRefresh.value = true;
         start();
         if (data.data) setContent(data.data);
         logTime.value = formatToDateTime(new Date());
+      } else {
+        showRefresh.value = false;
       }
     } catch (error) {
       closeModal();
@@ -89,7 +94,13 @@
       <div class="flex align-items-center">
         <div class="flex-1 text-left">{{ t('flink.app.view.refreshTime') }}:{{ logTime }}</div>
         <div class="button-group">
-          <a-button key="refresh" type="primary" @click="refreshLog" :loading="getLogLoading">
+          <a-button
+            key="refresh"
+            v-if="showRefresh"
+            type="primary"
+            @click="refreshLog"
+            :loading="getLogLoading"
+          >
             {{ t('flink.app.view.refresh') }}
           </a-button>
           <a-button key="close" type="primary" @click="closeModal()">
diff --git a/streampark-console/streampark-console-newui/src/views/flink/project/project.data.ts b/streampark-console/streampark-console-newui/src/views/flink/project/project.data.ts
index 4687c8a3e..44c1d16cf 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/project/project.data.ts
+++ b/streampark-console/streampark-console-newui/src/views/flink/project/project.data.ts
@@ -29,50 +29,23 @@ interface Status {
 }
 
 export const statusList: Status[] = [
-  {
-    label: 'All',
-    key: BuildStatusEnum.All,
-  },
-  {
-    label: 'Not Build',
-    key: BuildStatusEnum.NotBuild,
-  },
-  {
-    label: 'Building',
-    key: BuildStatusEnum.Building,
-  },
-  {
-    label: 'Build Success',
-    key: BuildStatusEnum.BuildSuccess,
-  },
-  {
-    label: 'Build Failed',
-    key: BuildStatusEnum.BuildFail,
-  },
+  { label: 'All', key: BuildStatusEnum.All },
+  { label: 'Not Build', key: BuildStatusEnum.NotBuild },
+  { label: 'Building', key: BuildStatusEnum.Building },
+  { label: 'Build Success', key: BuildStatusEnum.BuildSuccess },
+  { label: 'Build Failed', key: BuildStatusEnum.BuildFail },
 ];
 
 export const buildStateMap = {
-  [BuildStatusEnum.NotBuild]: {
-    color: '#C0C0C0',
-    label: 'NOT BUILD',
-  },
-  [BuildStatusEnum.NeedBuild]: {
-    color: '#FFA500',
-    label: 'NEED REBUILD',
-  },
+  [BuildStatusEnum.NotBuild]: { color: '#C0C0C0', label: 'NOT BUILD' },
+  [BuildStatusEnum.NeedBuild]: { color: '#FFA500', label: 'NEED REBUILD' },
   [BuildStatusEnum.Building]: {
     color: '#1AB58E',
     label: 'BUILDING',
     className: 'status-processing-building',
   },
-  [BuildStatusEnum.BuildSuccess]: {
-    color: '#52c41a',
-    label: 'SUCCESSFUL',
-  },
-  [BuildStatusEnum.BuildFail]: {
-    color: '#f5222d',
-    label: 'FAILED',
-  },
+  [BuildStatusEnum.BuildSuccess]: { color: '#52c41a', label: 'SUCCESSFUL' },
+  [BuildStatusEnum.BuildFail]: { color: '#f5222d', label: 'FAILED' },
 };
 
 export enum ProjectType {
diff --git a/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue b/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue
index a96424e49..466ee4df4 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue
@@ -181,10 +181,10 @@
     <ListItem v-for="(item, index) in clusters" :key="index">
       <ListItemMeta :title="item.clusterName" :description="item.description">
         <template #avatar>
-          <SvgIcon class="avatar" name="flink" size="25" />
+          <SvgIcon class="avatar p-15px" name="flink" size="60" />
         </template>
       </ListItemMeta>
-      <div class="list-content" style="width: 20%">
+      <div class="list-content" style="width: 15%">
         <div class="list-content-item" style="width: 60%">
           <span>ExecutionMode</span>
           <p style="margin-top: 10px">
@@ -192,7 +192,7 @@
           </p>
         </div>
       </div>
-      <div class="list-content" style="width: 20%">
+      <div class="list-content" style="width: 15%">
         <div class="list-content-item" style="width: 80%">
           <span>ClusterId</span>
           <p style="margin-top: 10px">
@@ -200,7 +200,7 @@
           </p>
         </div>
       </div>
-      <div class="list-content" style="width: 30%">
+      <div class="list-content" style="width: 20%">
         <div class="list-content-item" style="width: 60%">
           <span>Address</span>
           <p style="margin-top: 10px">
@@ -215,7 +215,7 @@
             v-auth="'app:update'"
             :disabled="true"
             @click="handleEditCluster(item)"
-            type="link"
+            shape="circle"
             size="large"
             class="control-button"
           >
@@ -225,7 +225,7 @@
             v-if="!handleIsStart(item) || item.executionMode === 1"
             v-auth="'app:update'"
             @click="handleEditCluster(item)"
-            type="link"
+            shape="circle"
             size="large"
             class="control-button"
           >
@@ -238,7 +238,7 @@
               v-if="item.executionMode === 3 || item.executionMode === 5"
               v-auth="'cluster:create'"
               @click="handleDeployCluser(item)"
-              type="link"
+              shape="circle"
               size="large"
               class="control-button"
             >
@@ -248,7 +248,7 @@
               v-else
               :disabled="true"
               v-auth="'cluster:create'"
-              type="link"
+              shape="circle"
               size="large"
               style="margin-left: 3px"
               class="control-button"
@@ -264,7 +264,7 @@
               v-if="[3, 5].includes(item.executionMode)"
               v-auth="'cluster:create'"
               @click="handleShutdownCluster(item)"
-              type="link"
+              shape="circle"
               size="large"
               style="margin-left: 3px"
               class="control-button"
@@ -275,7 +275,7 @@
               v-else
               :disabled="true"
               v-auth="'cluster:create'"
-              type="link"
+              shape="circle"
               size="large"
               class="control-button"
             >
@@ -289,7 +289,7 @@
             v-if="!handleIsStart(item)"
             v-auth="'app:detail'"
             :disabled="true"
-            type="link"
+            shape="circle"
             size="large"
             class="control-button"
           >
@@ -298,7 +298,7 @@
           <a-button
             v-else
             v-auth="'app:detail'"
-            type="link"
+            shape="circle"
             size="large"
             class="control-button"
             :href="item.address"
@@ -314,8 +314,8 @@
           :ok-text="t('common.yes')"
           @confirm="handleDelete(item)"
         >
-          <a-button type="link" size="large" class="control-button">
-            <DeleteOutlined style="color: red" />
+          <a-button type="danger" shape="circle" size="large" class="control-button">
+            <DeleteOutlined />
           </a-button>
         </Popconfirm>
       </template>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkEnvSetting.vue b/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkEnvSetting.vue
index cd9128520..d2aa39b7c 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkEnvSetting.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkEnvSetting.vue
@@ -94,7 +94,7 @@
     <ListItem v-for="(item, index) in flinks" :key="index">
       <ListItemMeta style="width: 60%" :title="item.flinkName" :description="item.description">
         <template #avatar>
-          <SvgIcon class="avatar" name="flink" size="25" />
+          <SvgIcon class="avatar p-15px" name="flink" size="60" />
         </template>
       </ListItemMeta>
 
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 4caa6a7e8..bb9b86f3f 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
@@ -59,9 +59,15 @@
         isPassword: () => false,
         data: settings.value.filter((i) => i.settingKey.indexOf('streampark.console') > -1),
       },
+      {
+        key: 5,
+        title: 'Ingrsss Setting',
+        isPassword: () => false,
+        data: settings.value.filter((i) => i.settingKey.indexOf('ingrsss') > -1),
+      },
     ];
   });
-  const collapseActive = ref(['1', '2', '3', '4']);
+  const collapseActive = ref(['1', '2', '3', '4', '5']);
   /* Get all system settings */
   async function getSettingAll() {
     const res = await fetchSystemSetting();
diff --git a/streampark-console/streampark-console-newui/src/views/system/member/Member.vue b/streampark-console/streampark-console-newui/src/views/system/member/Member.vue
index b00c7b66a..3716f7d1c 100644
--- a/streampark-console/streampark-console-newui/src/views/system/member/Member.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/member/Member.vue
@@ -18,7 +18,7 @@
 <template>
   <div>
     <BasicTable @register="registerTable" :formConfig="formConfig">
-      <template #form-advanceBefore>
+      <template #toolbar>
         <a-button type="primary" @click="handleCreate" v-auth="'member:add'">
           <Icon icon="ant-design:plus-outlined" />
           {{ t('common.add') }}
@@ -86,7 +86,7 @@
   const userStore = useUserStoreWithOut();
   const formConfig = computed((): Partial<FormProps> => {
     return {
-      labelWidth: 120,
+      baseColProps: { style: { paddingRight: '30px' } },
       colon: true,
       schemas: [
         {
@@ -116,6 +116,7 @@
     };
   });
   const [registerTable, { reload }] = useTable({
+    title: 'Member List',
     api: fetchMemberList,
     columns: [
       { title: t('system.member.table.userName'), dataIndex: 'userName', sorter: true },
@@ -126,7 +127,7 @@
     rowKey: 'id',
     pagination: true,
     useSearchForm: true,
-    showTableSetting: false,
+    showTableSetting: true,
     showIndexColumn: false,
     canResize: false,
     actionColumn: {
diff --git a/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue b/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue
index d49bce396..6474415b5 100644
--- a/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue
@@ -17,7 +17,7 @@
 <template>
   <div>
     <BasicTable @register="registerTable" @fetch-success="onFetchSuccess">
-      <template #form-advanceBefore>
+      <template #toolbar>
         <a-button type="primary" @click="handleCreate" v-auth="'menu:add'">
           <Icon icon="ant-design:plus-outlined" />
           {{ t('common.add') }}
@@ -62,11 +62,11 @@
       const { createMessage } = useMessage();
       const { t } = useI18n();
       const [registerTable, { reload, expandAll }] = useTable({
-        title: '',
+        title: 'Menu List',
         api: getMenuList,
         columns,
         formConfig: {
-          labelWidth: 120,
+          baseColProps: { style: { paddingRight: '30px' } },
           colon: true,
           schemas: searchFormSchema,
           fieldMapToTime: [['createTime', ['createTimeFrom', 'createTimeTo'], 'YYYY-MM-DD']],
@@ -78,7 +78,7 @@
         pagination: false,
         striped: false,
         useSearchForm: true,
-        showTableSetting: false,
+        showTableSetting: true,
         bordered: true,
         showIndexColumn: false,
         canResize: false,
diff --git a/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts b/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts
index bfd0bcaec..0a7073fa6 100644
--- a/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts
+++ b/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts
@@ -146,14 +146,12 @@ export const formSchema: FormSchema[] = [
     label: 'sort',
     component: 'InputNumber',
     componentProps: { class: '!w-full' },
-    required: true,
     ifShow: ({ values }) => !isButton(values.type),
   },
   {
     field: 'icon',
     label: 'icon',
     component: 'IconPicker',
-    required: true,
     ifShow: ({ values }) => !isButton(values.type),
   },
   {
diff --git a/streampark-console/streampark-console-newui/src/views/system/role/Role.vue b/streampark-console/streampark-console-newui/src/views/system/role/Role.vue
index a6ae86727..20d2e7ef1 100644
--- a/streampark-console/streampark-console-newui/src/views/system/role/Role.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/role/Role.vue
@@ -17,7 +17,7 @@
 <template>
   <div>
     <BasicTable @register="registerTable">
-      <template #form-advanceBefore>
+      <template #toolbar>
         <a-button type="primary" @click="handleCreate" v-auth="'role:add'">
           <Icon icon="ant-design:plus-outlined" />
           {{ t('common.add') }}
@@ -88,14 +88,16 @@
       const { createMessage } = useMessage();
       const useStore = useUserStoreWithOut();
       const [registerTable, { reload }] = useTable({
+        title: 'Role List',
         api: getRoleListByPage,
         columns,
         formConfig: {
-          labelWidth: 120,
+          baseColProps: { style: { paddingRight: '30px' } },
           schemas: searchFormSchema,
           colon: true,
           fieldMapToTime: [['createTime', ['createTimeFrom', 'createTimeTo'], 'YYYY-MM-DD']],
         },
+        showTableSetting: true,
         useSearchForm: true,
         showIndexColumn: false,
         canResize: false,
diff --git a/streampark-console/streampark-console-newui/src/views/system/role/role.data.ts b/streampark-console/streampark-console-newui/src/views/system/role/role.data.ts
index 4701044bd..72e94310d 100644
--- a/streampark-console/streampark-console-newui/src/views/system/role/role.data.ts
+++ b/streampark-console/streampark-console-newui/src/views/system/role/role.data.ts
@@ -57,8 +57,8 @@ export const searchFormSchema: FormSchema[] = [
 ];
 export async function handleRoleCheck(_rule: RuleObject, value: StoreValue) {
   if (value) {
-    if (value.length > 10) {
-      return Promise.reject('Role name should not be longer than 10 characters');
+    if (value.length > 255) {
+      return Promise.reject('Role name should not be longer than 255 characters');
     } else {
       const res = await fetchCheckName({
         roleName: value,
diff --git a/streampark-console/streampark-console-newui/src/views/system/team/Team.vue b/streampark-console/streampark-console-newui/src/views/system/team/Team.vue
index 253a5928e..13fe938f9 100644
--- a/streampark-console/streampark-console-newui/src/views/system/team/Team.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/team/Team.vue
@@ -17,7 +17,7 @@
 <template>
   <div>
     <BasicTable @register="registerTable">
-      <template #form-advanceBefore>
+      <template #toolbar>
         <a-button type="primary" @click="handleCreate" v-auth="'team:add'">
           <Icon icon="ant-design:plus-outlined" />
           {{ t('common.add') }}
@@ -70,11 +70,11 @@
       const { createMessage } = useMessage();
       const { t } = useI18n();
       const [registerTable, { reload }] = useTable({
-        // title: t('system.team.table.title'),
+        title: t('system.team.table.title'),
         api: fetTeamList,
         columns,
         formConfig: {
-          labelWidth: 120,
+          baseColProps: { style: { paddingRight: '30px' } },
           schemas: searchFormSchema,
           colon: true,
           fieldMapToTime: [['createTime', ['createTimeFrom', 'createTimeTo'], 'YYYY-MM-DD']],
@@ -82,7 +82,7 @@
         rowKey: 'id',
         pagination: true,
         useSearchForm: true,
-        showTableSetting: false,
+        showTableSetting: true,
         showIndexColumn: false,
         canResize: false,
         actionColumn: {
diff --git a/streampark-console/streampark-console-newui/src/views/system/token/Token.vue b/streampark-console/streampark-console-newui/src/views/system/token/Token.vue
index c758df00d..85fa51864 100644
--- a/streampark-console/streampark-console-newui/src/views/system/token/Token.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/token/Token.vue
@@ -17,7 +17,7 @@
 <template>
   <div>
     <BasicTable @register="registerTable">
-      <template #form-advanceBefore>
+      <template #toolbar>
         <a-button type="primary" @click="handleCreate" v-auth="'token:add'">
           <Icon icon="ant-design:plus-outlined" />
           {{ t('common.add') }}
@@ -73,11 +73,16 @@
       const [registerDrawer, { openDrawer }] = useDrawer();
       const { clipboardRef, copiedRef } = useCopyToClipboard();
       const [registerTable, { reload, updateTableDataRecord }] = useTable({
+        title: 'Token List',
         api: fetTokenList,
         columns,
-        formConfig: { labelWidth: 120, colon: true, schemas: searchFormSchema },
+        formConfig: {
+          baseColProps: { style: { paddingRight: '30px' } },
+          colon: true,
+          schemas: searchFormSchema,
+        },
         useSearchForm: true,
-        showTableSetting: false,
+        showTableSetting: true,
         rowKey: 'tokenId',
         showIndexColumn: false,
         canResize: false,
diff --git a/streampark-console/streampark-console-newui/src/views/system/token/components/TokenDrawer.vue b/streampark-console/streampark-console-newui/src/views/system/token/components/TokenDrawer.vue
new file mode 100644
index 000000000..2cb54c256
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/views/system/token/components/TokenDrawer.vue
@@ -0,0 +1,80 @@
+<!--
+  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.
+-->
+<template>
+  <BasicDrawer
+    okText="Submit"
+    @register="registerDrawer"
+    showFooter
+    :title="getTitle"
+    width="40%"
+    @ok="handleSubmit"
+  >
+    <BasicForm @register="registerForm" />
+  </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, computed, unref } from 'vue';
+  import { BasicForm, useForm } from '/@/components/Form';
+  import { formSchema } from '../token.data';
+  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+
+  import { fetchTokenCreate } from '/@/api/system/token';
+
+  export default defineComponent({
+    name: 'TokenDrawer',
+    components: { BasicDrawer, BasicForm },
+    emits: ['success', 'register'],
+    setup(_, { emit }) {
+      const isUpdate = ref(true);
+
+      const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
+        labelWidth: 120,
+        schemas: formSchema,
+        showActionButtonGroup: false,
+        baseColProps: { lg: 22, md: 22 },
+      });
+
+      const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
+        resetFields();
+        setDrawerProps({ confirmLoading: false });
+        isUpdate.value = !!data?.isUpdate;
+
+        if (unref(isUpdate)) {
+          setFieldsValue({
+            ...data.record,
+          });
+        }
+      });
+
+      const getTitle = computed(() => (!unref(isUpdate) ? 'Add Token' : 'Edit Token'));
+
+      async function handleSubmit() {
+        try {
+          const values = await validate();
+          setDrawerProps({ confirmLoading: true });
+          const res = await fetchTokenCreate(values);
+          closeDrawer();
+          emit('success', { isUpdate: unref(isUpdate), values: res });
+        } finally {
+          setDrawerProps({ confirmLoading: false });
+        }
+      }
+
+      return { registerDrawer, registerForm, getTitle, handleSubmit };
+    },
+  });
+</script>
diff --git a/streampark-console/streampark-console-newui/src/views/system/user/User.vue b/streampark-console/streampark-console-newui/src/views/system/user/User.vue
index 5997fdf4a..52afc18ef 100644
--- a/streampark-console/streampark-console-newui/src/views/system/user/User.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/user/User.vue
@@ -17,10 +17,10 @@
 <template>
   <div>
     <BasicTable @register="registerTable">
-      <template #form-advanceBefore>
+      <template #toolbar>
         <a-button type="primary" @click="handleCreate" v-auth="'user:add'">
           <Icon icon="ant-design:plus-outlined" />
-          {{ t('common.add') }}
+          Add New
         </a-button>
       </template>
       <template #bodyCell="{ column, record }">
@@ -63,11 +63,12 @@
       const [registerModal, { openModal }] = useModal();
       const { createMessage, Swal } = useMessage();
       const [registerTable, { reload }] = useTable({
-        title: '',
+        title: 'User List',
         api: getUserList,
         columns,
         formConfig: {
-          labelWidth: 120,
+          // labelWidth: 120,
+          baseColProps: { style: { paddingRight: '30px' } },
           schemas: searchFormSchema,
           colon: true,
           fieldMapToTime: [['createTime', ['createTimeFrom', 'createTimeTo'], 'YYYY-MM-DD']],
@@ -76,7 +77,7 @@
         pagination: true,
         striped: false,
         useSearchForm: true,
-        showTableSetting: false,
+        showTableSetting: true,
         bordered: false,
         showIndexColumn: false,
         canResize: false,
diff --git a/streampark-console/streampark-console-newui/src/views/system/user/components/UserDrawer.vue b/streampark-console/streampark-console-newui/src/views/system/user/components/UserDrawer.vue
index 20df3720c..20c7b647e 100644
--- a/streampark-console/streampark-console-newui/src/views/system/user/components/UserDrawer.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/user/components/UserDrawer.vue
@@ -48,14 +48,14 @@
         });
 
       const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
+        formType.value = data.formType;
         resetFields();
+        clearValidate();
+        updateSchema(formSchema(unref(formType)));
         setDrawerProps({
           confirmLoading: false,
           showFooter: data.formType !== FormTypeEnum.View,
         });
-        formType.value = data.formType;
-
-        updateSchema(formSchema(unref(formType)));
 
         if (unref(formType) !== FormTypeEnum.Create) {
           const roleIds = data.record?.roleId ?? [];
@@ -63,8 +63,6 @@
           setFieldsValue({
             ...data.record,
           });
-          clearValidate('username');
-          clearValidate('nickname');
         }
       });
 
diff --git a/streampark-console/streampark-console-newui/src/views/system/user/components/UserModal.vue b/streampark-console/streampark-console-newui/src/views/system/user/components/UserModal.vue
index 547dbda18..2d662bdac 100644
--- a/streampark-console/streampark-console-newui/src/views/system/user/components/UserModal.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/user/components/UserModal.vue
@@ -15,7 +15,7 @@
   limitations under the License.
 -->
 <template>
-  <BasicModal :width="600" @register="registerModal" @ok="handleSubmit">
+  <BasicModal :width="600" :show-cancel-btn="false" @register="registerModal" @ok="handleSubmit">
     <template #title>
       <Icon icon="ant-design:user-add-outlined" />
       User Info
diff --git a/streampark-console/streampark-console-newui/src/views/system/user/user.data.ts b/streampark-console/streampark-console-newui/src/views/system/user/user.data.ts
index 29afeacfe..e7e243253 100644
--- a/streampark-console/streampark-console-newui/src/views/system/user/user.data.ts
+++ b/streampark-console/streampark-console-newui/src/views/system/user/user.data.ts
@@ -34,19 +34,9 @@ const enum GenderEnum {
 }
 
 export const columns: BasicColumn[] = [
-  {
-    title: 'User Name',
-    dataIndex: 'username',
-    sorter: true,
-  },
-  {
-    title: 'Nick Name',
-    dataIndex: 'nickName',
-  },
-  {
-    title: 'User Type',
-    dataIndex: 'userType',
-  },
+  { title: 'User Name', dataIndex: 'username', sorter: true },
+  { title: 'Nick Name', dataIndex: 'nickName' },
+  { title: 'User Type', dataIndex: 'userType' },
   {
     title: 'Status',
     dataIndex: 'status',
@@ -70,18 +60,8 @@ export const columns: BasicColumn[] = [
 ];
 
 export const searchFormSchema: FormSchema[] = [
-  {
-    field: 'username',
-    label: 'User Name',
-    component: 'Input',
-    colProps: { span: 8 },
-  },
-  {
-    label: 'Create Time',
-    field: 'createTime',
-    component: 'RangePicker',
-    colProps: { span: 8 },
-  },
+  { field: 'username', label: 'User Name', component: 'Input', colProps: { span: 8 } },
+  { label: 'Create Time', field: 'createTime', component: 'RangePicker', colProps: { span: 8 } },
 ];
 
 export const formSchema = (formType: string): FormSchema[] => {
@@ -90,12 +70,7 @@ export const formSchema = (formType: string): FormSchema[] => {
   const isView = formType === FormTypeEnum.View;
 
   return [
-    {
-      field: 'userId',
-      label: 'User Id',
-      component: 'Input',
-      show: false,
-    },
+    { field: 'userId', label: 'User Id', component: 'Input', show: false },
     {
       field: 'username',
       label: 'User Name',
@@ -126,7 +101,9 @@ export const formSchema = (formType: string): FormSchema[] => {
       field: 'nickName',
       label: 'Nick Name',
       component: 'Input',
-      rules: [{ required: isCreate, message: 'nickName is required' }],
+      dynamicRules: () => {
+        return [{ required: isCreate, message: 'nickName is required' }];
+      },
       componentProps: { disabled: !isCreate },
     },
     {
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 878c776dd..d0be38577 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
@@ -17,7 +17,7 @@
 <template>
   <div>
     <BasicTable @register="registerTable">
-      <template #form-advanceBefore>
+      <template #toolbar>
         <a-button type="primary" @click="handleCreate" v-auth="'variable:add'">
           <Icon icon="ant-design:plus-outlined" />
           {{ t('common.add') }}
@@ -80,18 +80,18 @@
   const { createMessage } = useMessage();
   const { t } = useI18n();
   const [registerTable, { reload }] = useTable({
-    // title: t('system.variable.table.title'),
+    title: t('system.variable.table.title'),
     api: fetchVariableList,
     columns,
     formConfig: {
-      labelWidth: 120,
+      baseColProps: { style: { paddingRight: '30px' } },
       colon: true,
       schemas: searchFormSchema,
     },
     rowKey: 'id',
     pagination: true,
     useSearchForm: true,
-    showTableSetting: false,
+    showTableSetting: true,
     showIndexColumn: false,
     canResize: false,
     actionColumn: {