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/11/10 16:30:58 UTC

[incubator-streampark] branch dev updated: [Fix] user modal gender bug, flinksql editor fullscreen (#2000)

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 1c3566c4e [Fix] user modal gender bug, flinksql editor fullscreen (#2000)
1c3566c4e is described below

commit 1c3566c4ec8d82f92e2e1c2d53c286b1de407dee
Author: Sizhu Wang <12...@qq.com>
AuthorDate: Fri Nov 11 00:30:50 2022 +0800

    [Fix] user modal gender bug, flinksql editor fullscreen (#2000)
    
    * [Fix] user modal gender bug, flinksql editor fullscreen
    
    * [Fix] remove session cache
---
 .../components/Form/src/components/FormItem.vue    |   4 +-
 .../streampark-console-newui/src/design/index.less |  17 +++
 .../src/hooks/event/useFullscreen.ts               |  32 +++++
 .../src/locales/lang/en/flink/app.ts               |   1 +
 .../src/locales/lang/en/system/user.ts             |   5 +
 .../src/locales/lang/zh-CN/flink/app.ts            |   1 +
 .../src/locales/lang/zh-CN/system/user.ts          |   5 +
 .../src/store/modules/user.ts                      |   1 +
 .../src/views/base/login/Login.vue                 |   1 +
 .../src/views/flink/app/Add.vue                    |   1 -
 .../src/views/flink/app/View.vue                   |  21 ++-
 .../src/views/flink/app/components/FlinkSql.vue    | 157 +++++++++++++--------
 .../src/views/flink/app/components/ProgramArgs.vue |  70 +++++----
 .../src/views/flink/app/hooks/useAppTableAction.ts |   8 +-
 .../src/views/flink/app/styles/Add.less            |   6 +-
 .../views/system/user/components/UserDrawer.vue    |  14 +-
 .../src/views/system/user/components/UserModal.vue |  61 +++-----
 .../src/views/system/user/user.data.ts             |  36 ++---
 18 files changed, 283 insertions(+), 158 deletions(-)

diff --git a/streampark-console/streampark-console-newui/src/components/Form/src/components/FormItem.vue b/streampark-console/streampark-console-newui/src/components/Form/src/components/FormItem.vue
index ec851bb8a..c20af86bd 100644
--- a/streampark-console/streampark-console-newui/src/components/Form/src/components/FormItem.vue
+++ b/streampark-console/streampark-console-newui/src/components/Form/src/components/FormItem.vue
@@ -373,7 +373,9 @@
             >
               {showBeforeItem && <div class="extra">{getBeforeItem}</div>}
               <div style="display:flex">
-                <div style="flex:1;">{getContent()}</div>
+                <div class="w-full" style="flex:1;">
+                  {getContent()}
+                </div>
                 {showSuffix && <span class="suffix">{getSuffix}</span>}
               </div>
               {showAfterItem && <div class="extra">{getAfterItem}</div>}
diff --git a/streampark-console/streampark-console-newui/src/design/index.less b/streampark-console/streampark-console-newui/src/design/index.less
index 38f10a0c6..35209f0bf 100644
--- a/streampark-console/streampark-console-newui/src/design/index.less
+++ b/streampark-console/streampark-console-newui/src/design/index.less
@@ -84,3 +84,20 @@ span {
   border: 1px solid rgba(122 200 255/ 20%) !important;
   background-color: rgba(122 200 255 / 20%);
 }
+
+.box-content__full {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 600;
+  height: auto !important;
+  background-color: @background-color-base;
+  padding: 10px;
+}
+
+.basic-title {
+  font-size: 18px;
+  font-weight: bold;
+}
diff --git a/streampark-console/streampark-console-newui/src/hooks/event/useFullscreen.ts b/streampark-console/streampark-console-newui/src/hooks/event/useFullscreen.ts
index cad2c86b6..b96b5fd23 100644
--- a/streampark-console/streampark-console-newui/src/hooks/event/useFullscreen.ts
+++ b/streampark-console/streampark-console-newui/src/hooks/event/useFullscreen.ts
@@ -36,3 +36,35 @@ export const useFullscreenEvent = (gloabl = false) => {
     getTitle,
   };
 };
+
+export const useFullContent = () => {
+  const fullScreenStatus = ref(false);
+  const { t } = useI18n();
+
+  const getTitle = computed(() => {
+    return unref(fullScreenStatus)
+      ? t('layout.header.tooltipExitFull')
+      : t('layout.header.tooltipEntryFull');
+  });
+  function toggle() {
+    fullScreenStatus.value = !fullScreenStatus.value;
+  }
+  const fullContentClass = computed(() => {
+    return {
+      [`box-content__full`]: fullScreenStatus.value,
+    };
+  });
+  const fullEditorClass = computed(() => {
+    return {
+      [`h-[calc(100%-20px)]`]: !fullScreenStatus.value,
+      [`h-[calc(100%-88px)]`]: fullScreenStatus.value,
+    };
+  });
+  return {
+    fullEditorClass,
+    fullContentClass,
+    fullScreenStatus,
+    getTitle,
+    toggle,
+  };
+};
diff --git a/streampark-console/streampark-console-newui/src/locales/lang/en/flink/app.ts b/streampark-console/streampark-console-newui/src/locales/lang/en/flink/app.ts
index f64ef91cb..09f66abe4 100644
--- a/streampark-console/streampark-console-newui/src/locales/lang/en/flink/app.ts
+++ b/streampark-console/streampark-console-newui/src/locales/lang/en/flink/app.ts
@@ -71,6 +71,7 @@ export default {
   },
   dependencyError: 'please set flink version first.',
   flinkSql: {
+    preview: 'Preview',
     verify: 'Verify',
     format: 'Format',
     fullScreen: 'Full Screen',
diff --git a/streampark-console/streampark-console-newui/src/locales/lang/en/system/user.ts b/streampark-console/streampark-console-newui/src/locales/lang/en/system/user.ts
index 875ffb99b..ed9d0f68b 100644
--- a/streampark-console/streampark-console-newui/src/locales/lang/en/system/user.ts
+++ b/streampark-console/streampark-console-newui/src/locales/lang/en/system/user.ts
@@ -48,4 +48,9 @@ export default {
   },
   roleInfo: 'Role Info',
   modifyTime: 'Not yet modified',
+  male: 'male',
+  female: 'female',
+  secret: 'secret',
+  locked: 'locked',
+  effective: 'effective',
 };
diff --git a/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/flink/app.ts b/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/flink/app.ts
index a822a3c8d..0e5037824 100644
--- a/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/flink/app.ts
+++ b/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/flink/app.ts
@@ -70,6 +70,7 @@ export default {
   },
   dependencyError: '请先检查flink 版本.',
   flinkSql: {
+    preview: '内容预览',
     verify: '验证',
     format: '格式化',
     fullScreen: '全屏',
diff --git a/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/system/user.ts b/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/system/user.ts
index 3c9f9642b..bba652d1b 100644
--- a/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/system/user.ts
+++ b/streampark-console/streampark-console-newui/src/locales/lang/zh-CN/system/user.ts
@@ -48,4 +48,9 @@ export default {
   },
   roleInfo: '角色信息',
   modifyTime: '尚未修改',
+  male: '男',
+  female: '女',
+  secret: '未知',
+  locked: '锁定',
+  effective: '有效',
 };
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 7ab760369..caf354214 100644
--- a/streampark-console/streampark-console-newui/src/store/modules/user.ts
+++ b/streampark-console/streampark-console-newui/src/store/modules/user.ts
@@ -216,6 +216,7 @@ export const useUserStore = defineStore({
       this.setSessionTimeout(false);
       this.setUserInfo(null);
       sessionStorage.removeItem(APP_TEAMID_KEY_);
+      sessionStorage.removeItem('appPageNo');
       localStorage.removeItem(APP_TEAMID_KEY_);
       this.setToken(undefined);
       goLogin && router.push(PageEnum.BASE_LOGIN);
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 e728e74a2..5be2b1e7e 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
@@ -79,6 +79,7 @@
 
   // const globSetting = useGlobSetting();
   const { prefixCls } = useDesign('login');
+  sessionStorage.removeItem('appPageNo');
   // const title = computed(() => globSetting?.title ?? '');
 </script>
 <style lang="less">
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/Add.vue b/streampark-console/streampark-console-newui/src/views/flink/app/Add.vue
index 1382a822f..1f7e20511 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/Add.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/Add.vue
@@ -94,7 +94,6 @@
     const defaultValue = {
       resolveOrder: 0,
       k8sRestExposedType: 0,
-      restartSize: 1,
     };
     options.forEach((item) => {
       defaultValue[item.key] = item.defaultValue;
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 16f6c6a5f..1767cc5f3 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
@@ -15,7 +15,7 @@
   limitations under the License.
 -->
 <script lang="ts">
-  import { defineComponent, nextTick, ref, unref, onUnmounted } from 'vue';
+  import { defineComponent, nextTick, ref, unref, onUnmounted, onMounted } from 'vue';
   import { useAppTableAction } from './hooks/useAppTableAction';
   import { useI18n } from '/@/hooks/web/useI18n';
 
@@ -53,13 +53,14 @@
   const appDashboardRef = ref<any>();
 
   const yarn = ref<Nullable<string>>(null);
+  const currentTablePage = ref(1);
 
   const [registerStartModal, { openModal: openStartModal }] = useModal();
   const [registerStopModal, { openModal: openStopModal }] = useModal();
   const [registerLogModal, { openModal: openLogModal }] = useModal();
   const [registerBuildDrawer, { openDrawer: openBuildDrawer }] = useDrawer();
 
-  const [registerTable, { reload, getLoading }] = useTable({
+  const [registerTable, { reload, getLoading, setPagination }] = useTable({
     rowKey: 'id',
     api: fetchAppRecord,
     beforeFetch: (params) => {
@@ -69,6 +70,8 @@
         }
         delete params.state;
       }
+      currentTablePage.value = params.pageNum;
+      // sessionStorage.setItem('appPageNo', params.pageNum);
       return params;
     },
     afterFetch: (dataSource) => {
@@ -114,6 +117,7 @@
     tableSetting: { fullScreen: true, redo: false },
     actionColumn: { dataIndex: 'operation', title: t('component.table.operation'), width: 180 },
   });
+
   const { getTableActions, getActionDropdown, formConfig } = useAppTableAction(
     openStartModal,
     openStopModal,
@@ -160,6 +164,17 @@
     start();
   }, 2000);
 
+  onMounted(() => {
+    // If there is a page, jump to the page number of the record
+    const currentPage = sessionStorage.getItem('appPageNo');
+    if (currentPage) {
+      setPagination({
+        current: Number(currentPage) || 1,
+      });
+      sessionStorage.removeItem('appPageNo');
+    }
+  });
+
   onUnmounted(() => {
     stop();
   });
@@ -226,7 +241,7 @@
         </template>
         <template v-if="column.dataIndex === 'operation'">
           <TableAction
-            :actions="getTableActions(record)"
+            :actions="getTableActions(record, currentTablePage)"
             :dropDownActions="getActionDropdown(record)"
           />
         </template>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSql.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSql.vue
index d26df0254..d0bcebf2b 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSql.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSql.vue
@@ -17,13 +17,16 @@
 <script lang="ts">
   export default {
     name: 'FlinkSql',
+    components: { SvgIcon },
   };
 </script>
 
 <script setup lang="ts" name="FlinkSql">
-  import { computed, reactive, ref, unref, watchEffect } from 'vue';
+  import { computed, reactive, ref, watchEffect } from 'vue';
+  import { Tooltip } from 'ant-design-vue';
+  import { FullscreenExitOutlined } from '@ant-design/icons-vue';
   import { getMonacoOptions } from '../data';
-  import { Icon } from '/@/components/Icon';
+  import { Icon, SvgIcon } from '/@/components/Icon';
   import { useMonaco } from '/@/hooks/web/useMonaco';
   import { Button } from 'ant-design-vue';
   import { isEmpty } from '/@/utils/is';
@@ -31,17 +34,19 @@
   import { fetchFlinkSqlVerify } from '/@/api/flink/app/flinkSql';
   import { format } from '../FlinkSqlFormatter';
   import { useI18n } from '/@/hooks/web/useI18n';
-  import { useFullscreenEvent } from '/@/hooks/event/useFullscreen';
+  import { useFullContent } from '/@/hooks/event/useFullscreen';
   const ButtonGroup = Button.Group;
   const { t } = useI18n();
+
+  const flinkSql = ref();
   const vertifyRes = reactive({
     errorMsg: '',
     verified: false,
     errorStart: 0,
     errorEnd: 0,
   });
-  const flinkSql = ref();
-  const { fullscreenRef, isFullscreen, toggle } = useFullscreenEvent();
+
+  const { toggle, fullContentClass, fullEditorClass, fullScreenStatus } = useFullContent();
   const emit = defineEmits(['update:value', 'preview']);
   const { createMessage } = useMessage();
 
@@ -115,10 +120,10 @@
         try {
           monaco.editor.setModelMarkers(model, 'sql', [
             {
-              startLineNumber: 1,
-              endLineNumber: 4,
+              startLineNumber: vertifyRes.errorStart,
+              endLineNumber: vertifyRes.errorEnd,
               severity: monaco.MarkerSeverity.Error,
-              message: 'dsadfs',
+              message: vertifyRes.errorMsg,
             },
           ]);
         } catch (e) {
@@ -136,14 +141,14 @@
     setContent(formatSql);
   }
   /* full screen */
-  function handleBigScreen() {
-    toggle();
-    unref(flinkSql).style.width = '0';
-    setTimeout(() => {
-      unref(flinkSql).style.width = '100%';
-      unref(flinkSql).style.height = isFullscreen.value ? 'calc(100vh - 50px)' : '550px';
-    }, 500);
-  }
+  // function handleBigScreen() {
+  //   toggle();
+  //   unref(flinkSql).style.width = '0';
+  //   setTimeout(() => {
+  //     unref(flinkSql).style.width = '100%';
+  //     unref(flinkSql).style.height = isFullscreen.value ? 'calc(100vh - 50px)' : '550px';
+  //   }, 500);
+  // }
   const { onChange, setContent, getInstance, getMonacoInstance, setMonacoSuggest } = useMonaco(
     flinkSql,
     {
@@ -165,6 +170,12 @@
   const canPreview = computed(() => {
     return /\${.+}/.test(props.value);
   });
+  const flinkEditorClass = computed(() => {
+    return {
+      ...fullEditorClass.value,
+      ['syntax-' + (vertifyRes.errorMsg ? 'false' : 'true')]: true,
+    };
+  });
 
   onChange((data) => {
     emit('update:value', data);
@@ -174,49 +185,85 @@
 </script>
 
 <template>
-  <div>
-    <div ref="fullscreenRef">
-      <div
-        class="sql-box"
-        ref="flinkSql"
-        :class="'syntax-' + (vertifyRes.errorMsg ? 'false' : 'true')"
-      ></div>
-      <ButtonGroup class="flinksql-tool">
-        <a-button
-          class="flinksql-tool-item"
-          size="small"
-          v-if="canPreview"
-          @click="emit('preview', value)"
-        >
-          <Icon icon="ant-design:eye-outlined" />
-          preview
+  <div style="height: 550px" class="w-full" :class="fullContentClass">
+    <div
+      class="full-content-tool flex justify-between px-20px border-solid border-b pb-10px mb-10px"
+      v-if="fullScreenStatus"
+    >
+      <div class="flex items-center">
+        <SvgIcon name="fql" />
+        <div class="basic-title ml-10px">Flink Sql</div>
+      </div>
+      <Tooltip :title="t('component.modal.restore')" placement="bottom">
+        <FullscreenExitOutlined role="full" @click="toggle" style="font-size: 18px" />
+      </Tooltip>
+    </div>
+
+    <div ref="flinkSql" class="overflow-hidden w-full mt-5px" :class="flinkEditorClass"></div>
+    <ButtonGroup class="flinksql-tool" v-if="!fullScreenStatus">
+      <a-button
+        class="flinksql-tool-item"
+        size="small"
+        v-if="canPreview"
+        @click="emit('preview', value)"
+      >
+        <Icon icon="ant-design:eye-outlined" />
+        {{ t('flink.app.flinkSql.preview') }}
+      </a-button>
+      <a-button size="small" class="flinksql-tool-item" type="primary" @click="handleVerifySql">
+        <Icon icon="ant-design:check-outlined" />
+        {{ t('flink.app.flinkSql.verify') }}
+      </a-button>
+      <a-button class="flinksql-tool-item" size="small" type="default" @click="handleFormatSql">
+        <Icon icon="ant-design:thunderbolt-outlined" />
+        {{ t('flink.app.flinkSql.format') }}
+      </a-button>
+      <a-button class="flinksql-tool-item" size="small" type="default" @click="toggle">
+        <Icon icon="ant-design:fullscreen-outlined" />
+        {{ t('flink.app.flinkSql.fullScreen') }}
+      </a-button>
+    </ButtonGroup>
+    <div class="flex items-center justify-between" v-else>
+      <div class="mt-10px flex-1 mr-10px overflow-hidden whitespace-nowrap">
+        <div class="text-red-600 overflow-ellipsis overflow-hidden" v-if="vertifyRes.errorMsg">
+          {{ vertifyRes.errorMsg }}
+        </div>
+        <div v-else class="text-green-700">
+          <span v-if="vertifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
+        </div>
+      </div>
+      <div class="flinksql-tool">
+        <a-button v-if="canPreview" @click="emit('preview', value)">
+          <div class="flex items-center">
+            <Icon icon="ant-design:eye-outlined" />
+            {{ t('flink.app.flinkSql.preview') }}
+          </div>
         </a-button>
-        <a-button size="small" class="flinksql-tool-item" type="primary" @click="handleVerifySql">
-          <Icon icon="ant-design:check-outlined" />
-          {{ t('flink.app.flinkSql.verify') }}
+        <a-button type="primary" @click="handleVerifySql" class="ml-10px">
+          <div class="flex items-center">
+            <Icon icon="ant-design:check-outlined" />
+            {{ t('flink.app.flinkSql.verify') }}
+          </div>
         </a-button>
-        <a-button class="flinksql-tool-item" size="small" type="default" @click="handleFormatSql">
-          <Icon icon="ant-design:thunderbolt-outlined" />
-          {{ t('flink.app.flinkSql.format') }}
+        <a-button type="default" @click="handleFormatSql" class="ml-10px">
+          <div class="flex items-center">
+            <Icon icon="ant-design:thunderbolt-outlined" />
+            {{ t('flink.app.flinkSql.format') }}
+          </div>
         </a-button>
-        <a-button class="flinksql-tool-item" size="small" type="default" @click="handleBigScreen">
-          <Icon
-            :icon="
-              isFullscreen
-                ? 'ant-design:fullscreen-exit-outlined'
-                : 'ant-design:fullscreen-outlined'
-            "
-          />
-          {{ isFullscreen ? t('flink.app.flinkSql.exit') : '' }}
-          {{ t('flink.app.flinkSql.fullScreen') }}
+        <a-button type="default" @click="toggle" class="ml-10px">
+          <div class="flex items-center">
+            <Icon icon="ant-design:fullscreen-exit-outlined" />
+            {{ t('layout.header.tooltipExitFull') }}
+          </div>
         </a-button>
-      </ButtonGroup>
-      <p class="conf-desc mt-10px">
-        <span class="text-red-600" v-if="vertifyRes.errorMsg"> {{ vertifyRes.errorMsg }} </span>
-        <span v-else class="text-green-700">
-          <span v-if="vertifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
-        </span>
-      </p>
+      </div>
     </div>
   </div>
+  <p class="conf-desc mt-10px" v-if="!fullScreenStatus">
+    <span class="text-red-600" v-if="vertifyRes.errorMsg"> {{ vertifyRes.errorMsg }} </span>
+    <span v-else class="text-green-700">
+      <span v-if="vertifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
+    </span>
+  </p>
 </template>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/ProgramArgs.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/ProgramArgs.vue
index 8e83887ed..9f601e14e 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/ProgramArgs.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/ProgramArgs.vue
@@ -15,9 +15,21 @@
   limitations under the License.
 -->
 <template>
-  <div ref="fullscreenRef">
-    <div ref="programArgRef" class="w-full border mt-5px" style="height: 240px"> </div>
-    <div class="relative flinksql-tool">
+  <div style="height: 340px" :class="fullContentClass">
+    <div
+      class="full-content-tool flex justify-between px-20px border-solid border-b pb-10px mb-10px"
+      v-if="fullScreenStatus"
+    >
+      <div class="basic-title">
+        <Icon icon="material-symbols:energy-program-saving" color="#477de9" />
+        Program args
+      </div>
+      <Tooltip :title="t('component.modal.restore')" placement="bottom">
+        <FullscreenExitOutlined role="full" @click="toggle" style="font-size: 18px" />
+      </Tooltip>
+    </div>
+    <div ref="programArgRef" :class="fullEditorClass" class="w-full program-box mt-5px"> </div>
+    <div class="relative flinksql-tool" v-if="!fullScreenStatus">
       <a-button
         class="flinksql-tool-item"
         v-if="canReview"
@@ -25,16 +37,25 @@
         size="small"
       >
         <Icon icon="ant-design:eye-outlined" />
-        preview
+        {{ t('flink.app.flinkSql.preview') }}
       </a-button>
-      <a-button
-        class="flinksql-tool-item"
-        size="small"
-        :type="isFullscreen ? 'default' : 'primary'"
-        @click="handleBigScreen"
-      >
-        <Icon :icon="`ant-design:${isFullscreen ? 'fullscreen-exit' : 'fullscreen'}-outlined`" />
-        {{ getTitle }}
+      <a-button class="flinksql-tool-item" size="small" type="default" @click="toggle">
+        <Icon icon="ant-design:fullscreen-outlined" />
+        {{ t('layout.header.tooltipEntryFull') }}
+      </a-button>
+    </div>
+    <div v-else class="text-right py-10px">
+      <a-button type="primary" v-if="canReview" @click="emit('preview', value)">
+        <div class="flex items-center">
+          <Icon icon="ant-design:eye-outlined" />
+          {{ t('flink.app.flinkSql.preview') }}
+        </div>
+      </a-button>
+      <a-button type="primary" @click="toggle" class="ml-10px">
+        <div class="flex items-center">
+          <Icon icon="ant-design:fullscreen-exit-outlined" />
+          {{ t('layout.header.tooltipExitFull') }}
+        </div>
       </a-button>
     </div>
   </div>
@@ -45,11 +66,15 @@
   };
 </script>
 <script lang="ts" setup>
-  import { computed, ref, toRefs, unref, watchEffect } from 'vue';
+  import { Tooltip } from 'ant-design-vue';
+  import { FullscreenExitOutlined } from '@ant-design/icons-vue';
+  import { computed, ref, toRefs, watchEffect } from 'vue';
   import { getMonacoOptions } from '../data';
   import Icon from '/@/components/Icon';
+  import { useFullContent } from '/@/hooks/event/useFullscreen';
+  import { useI18n } from '/@/hooks/web/useI18n';
   import { useMonaco } from '/@/hooks/web/useMonaco';
-  import { useFullscreenEvent } from '/@/hooks/event/useFullscreen';
+  const { t } = useI18n();
   const props = defineProps({
     value: {
       type: String,
@@ -63,8 +88,8 @@
   const { value, suggestions } = toRefs(props);
   const emit = defineEmits(['update:value', 'preview']);
   const programArgRef = ref();
-  const { fullscreenRef, isFullscreen, toggle, getTitle } = useFullscreenEvent();
 
+  const { toggle, fullContentClass, fullEditorClass, fullScreenStatus } = useFullContent();
   const { onChange, setContent, setMonacoSuggest } = useMonaco(programArgRef, {
     language: 'plaintext',
     code: '',
@@ -81,17 +106,14 @@
   const canReview = computed(() => {
     return /\${.+}/.test(value.value);
   });
-  /* full screen */
-  function handleBigScreen() {
-    toggle();
-    unref(programArgRef).style.width = '0';
-    setTimeout(() => {
-      unref(programArgRef).style.width = '100%';
-      unref(programArgRef).style.height = isFullscreen.value ? 'calc(100vh - 50px)' : '240px';
-    }, 500);
-  }
+
   onChange((data) => {
     emit('update:value', data);
   });
   defineExpose({ setContent });
 </script>
+<style lang="less">
+  .program-box {
+    border: 1px solid @border-color-base;
+  }
+</style>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts
index ae118a3c9..d1811e2f6 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts
@@ -59,13 +59,13 @@ export const useAppTableAction = (
   } = useFlinkApplication(openStartModal);
 
   /* Operation button */
-  function getTableActions(record: AppListRecord): ActionItem[] {
+  function getTableActions(record: AppListRecord, currentPgaeNo: any): ActionItem[] {
     return [
       {
         tooltip: { title: t('flink.app.tableAction.edit') },
         auth: 'app:update',
         icon: 'clarity:note-edit-line',
-        onClick: handleEdit.bind(null, record),
+        onClick: handleEdit.bind(null, record, currentPgaeNo),
       },
       {
         tooltip: { title: t('flink.app.tableAction.launch') },
@@ -118,7 +118,9 @@ export const useAppTableAction = (
     ];
   }
   /* Click to edit */
-  function handleEdit(app: AppListRecord) {
+  function handleEdit(app: AppListRecord, currentPageNo: number) {
+    // Record the current page number
+    sessionStorage.setItem('appPageNo', String(currentPageNo || 1));
     flinkAppStore.setApplicationId(app.id);
     if (app.appType === 1) {
       // jobType( 1 custom code 2: flinkSQL)
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less b/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less
index 3fda47049..d8cc44cd7 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less
@@ -190,14 +190,13 @@
     margin-top: 15px;
     margin-bottom: -10px;
     border-radius: 5px;
-    background-color: #e6f7ff;
-    border: 1px solid #d9d9d9;
+    background-color: @background-color-base;
+    border: 1px solid @border-color-base;
     display: inline-block;
 
     .dependency-item {
       position: relative;
       border: unset;
-      background-color: unset;
       line-height: 35px;
       padding: 0 6px;
       width: unset;
@@ -207,6 +206,7 @@
         position: relative;
         left: 5px;
         top: 6px;
+        color: @background-color-base;
       }
     }
   }
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 3d425bed8..e53544abb 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
@@ -15,7 +15,13 @@
   limitations under the License.
 -->
 <template>
-  <BasicDrawer okText="Submit" @register="registerDrawer" showFooter width="40%" @ok="handleSubmit">
+  <BasicDrawer
+    :okText="t('common.submitText')"
+    @register="registerDrawer"
+    showFooter
+    width="40%"
+    @ok="handleSubmit"
+  >
     <template #title>
       <Icon icon="ant-design:user-add-outlined" />
       {{ getTitle }}
@@ -63,9 +69,7 @@
         if (unref(formType) !== FormTypeEnum.Create) {
           const roleIds = data.record?.roleId ?? [];
           data.record.roleId = Array.isArray(roleIds) ? roleIds : roleIds.split(',');
-          setFieldsValue({
-            ...data.record,
-          });
+          setFieldsValue(data.record);
         }
       });
 
@@ -89,7 +93,7 @@
         }
       }
 
-      return { registerDrawer, registerForm, getTitle, handleSubmit };
+      return { t, registerDrawer, registerForm, getTitle, handleSubmit };
     },
   });
 </script>
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 d9778d858..f4cd01a8b 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,17 +15,12 @@
   limitations under the License.
 -->
 <template>
-  <BasicModal :width="600" :show-cancel-btn="false" @register="registerModal" @ok="handleSubmit">
+  <BasicModal :width="600" :show-cancel-btn="false" @register="registerModal" @ok="closeModal">
     <template #title>
       <Icon icon="ant-design:user-add-outlined" />
       {{ t('system.user.userInfo') }}
     </template>
-    <Description
-      @register="registerDescription"
-      :column="1"
-      :data="userInfo"
-      :schema="userColumn"
-    />
+    <Description :column="1" :data="userInfo" :schema="userColumn" />
   </BasicModal>
 </template>
 <script lang="ts">
@@ -37,33 +32,20 @@
 <script setup lang="ts">
   import { Tag } from 'ant-design-vue';
   import { defineComponent, h, ref } from 'vue';
-  import { useDescription, Description } from '/@/components/Description';
+  import { GenderEnum, StatusEnum } from '../user.data';
+  import { DescItem, Description } from '/@/components/Description';
   import Icon from '/@/components/Icon';
   import { useModalInner, BasicModal } from '/@/components/Modal';
   import { useI18n } from '/@/hooks/web/useI18n';
+
   const userInfo = ref<Recordable>({});
 
   const { t } = useI18n();
   const [registerModal, { closeModal }] = useModalInner((data: Recordable) => {
     data && onReceiveModalData(data);
   });
-  function onReceiveModalData(data) {
-    userInfo.value = {};
-    switch (data.sex) {
-      case '0':
-        data.sexText = 'male';
-        break;
-      case '1':
-        data.sexText = 'female';
-        break;
-      case '2':
-        data.sexText = 'secret';
-        break;
-      default:
-        data.sexText = data.sex;
-        break;
-    }
-    Object.assign(userInfo.value, data);
+  function onReceiveModalData(data: Recordable) {
+    userInfo.value = Object.assign({}, userInfo.value, data);
   }
   // Dynamically generate label icons
   const generatedLabelIcon = (icon: string, label: string) => {
@@ -72,31 +54,30 @@
       h('span', { class: 'px-5px' }, label),
     ]);
   };
-  const userColumn = [
+  const userColumn: DescItem[] = [
     { label: generatedLabelIcon('user', t('system.user.form.userName')), field: 'username' },
     { label: generatedLabelIcon('star', t('system.user.form.userType')), field: 'userType' },
     {
       label: generatedLabelIcon('skin', t('system.user.form.gender')),
       field: 'sex',
-      render: (curVal: string) => {
+      render: (curVal: string | number) => {
         const sexMap = {
-          '0': 'male',
-          '1': 'female',
-          '2': 'secret',
-          [curVal]: curVal,
+          [GenderEnum.Male]: t('system.user.male'),
+          [GenderEnum.Female]: t('system.user.female'),
+          [GenderEnum.Other]: t('system.user.secret'),
         };
-        return sexMap[curVal];
+        return sexMap[curVal] || curVal;
       },
     },
     { label: generatedLabelIcon('mail', 'E-Mail'), field: 'email' },
     {
-      label: generatedLabelIcon(`${userInfo.value?.status === '1' ? 'smile' : 'frown'}`, 'Status'),
+      label: generatedLabelIcon('smile', t('system.user.form.status')),
       field: 'status',
-      render: (curVal) => {
-        if (curVal === '0') {
-          return h(Tag, { color: 'red' }, () => 'locked');
-        } else if (curVal === '1') {
-          return h(Tag, { color: 'green' }, () => 'effective');
+      render: (curVal: string | number) => {
+        if (curVal == StatusEnum.Locked) {
+          return h(Tag, { color: 'red' }, () => t('system.user.locked'));
+        } else if (curVal == StatusEnum.Effective) {
+          return h(Tag, { color: 'green' }, () => t('system.user.effective'));
         } else {
           return h('span', null, curVal);
         }
@@ -115,8 +96,4 @@
       field: 'description',
     },
   ];
-  const [registerDescription] = useDescription();
-  function handleSubmit() {
-    closeModal();
-  }
 </script>
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 634b324c5..fe858f226 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
@@ -22,13 +22,13 @@ import { FormTypeEnum } from '/@/enums/formEnum';
 import { useI18n } from '/@/hooks/web/useI18n';
 const { t } = useI18n();
 // user status enum
-const enum StatusEnum {
+export const enum StatusEnum {
   Effective = '1',
   Locked = '0',
 }
 
 // gender
-const enum GenderEnum {
+export const enum GenderEnum {
   Male = '0',
   Female = '1',
   Other = '2',
@@ -44,12 +44,12 @@ export const columns: BasicColumn[] = [
     customRender: ({ record }) => {
       const enable = record?.status === StatusEnum.Effective;
       const color = enable ? 'green' : 'red';
-      const text = enable ? 'Effective' : 'locked';
+      const text = enable ? t('system.user.effective') : t('system.user.locked');
       return h(Tag, { color }, () => text);
     },
     filters: [
-      { text: 'Effective', value: '1' },
-      { text: 'Locked', value: '0' },
+      { text: t('system.user.effective'), value: StatusEnum.Effective },
+      { text: t('system.user.locked'), value: StatusEnum.Locked },
     ],
     filterMultiple: false,
   },
@@ -68,8 +68,8 @@ export const searchFormSchema: FormSchema[] = [
     colProps: { span: 8 },
   },
   {
-    label: t('common.createTime'),
     field: 'createTime',
+    label: t('common.createTime'),
     component: 'RangePicker',
     colProps: { span: 8 },
   },
@@ -103,10 +103,7 @@ export const formSchema = (formType: string): FormSchema[] => {
           trigger: 'blur',
         },
       ],
-      componentProps: {
-        id: 'formUserName',
-        disabled: !isCreate,
-      },
+      componentProps: { id: 'formUserName', disabled: !isCreate },
     },
     {
       field: 'nickName',
@@ -121,7 +118,6 @@ export const formSchema = (formType: string): FormSchema[] => {
       field: 'password',
       label: t('system.user.form.password'),
       component: 'InputPassword',
-      componentProps: { placeholder: 'please enter password' },
       helpMessage: t('system.user.form.passwordHelp'),
       rules: [
         { required: true, message: t('system.user.form.passwordRequire') },
@@ -140,7 +136,6 @@ export const formSchema = (formType: string): FormSchema[] => {
       ],
       componentProps: {
         readonly: isView,
-        placeholder: 'please enter email',
       },
     },
     {
@@ -150,9 +145,8 @@ export const formSchema = (formType: string): FormSchema[] => {
       componentProps: {
         disabled: isView,
         api: fetchUserTypes,
-        placeholder: 'Please select a user type',
       },
-      rules: [{ required: true, message: 'Please select a user type' }],
+      rules: [{ required: true }],
     },
     {
       field: 'status',
@@ -161,11 +155,11 @@ export const formSchema = (formType: string): FormSchema[] => {
       defaultValue: StatusEnum.Effective,
       componentProps: {
         options: [
-          { label: 'locked', value: StatusEnum.Locked },
-          { label: 'effective', value: StatusEnum.Effective },
+          { label: t('system.user.locked'), value: StatusEnum.Locked },
+          { label: t('system.user.effective'), value: StatusEnum.Effective },
         ],
       },
-      rules: [{ required: true, message: 'please select status' }],
+      rules: [{ required: true }],
     },
     {
       field: 'sex',
@@ -174,9 +168,9 @@ export const formSchema = (formType: string): FormSchema[] => {
       defaultValue: GenderEnum.Male,
       componentProps: {
         options: [
-          { label: 'male', value: GenderEnum.Male },
-          { label: 'female', value: GenderEnum.Female },
-          { label: 'secret', value: GenderEnum.Other },
+          { label: t('system.user.male'), value: GenderEnum.Male },
+          { label: t('system.user.female'), value: GenderEnum.Female },
+          { label: t('system.user.secret'), value: GenderEnum.Other },
         ],
       },
       required: true,
@@ -185,7 +179,7 @@ export const formSchema = (formType: string): FormSchema[] => {
       field: 'description',
       label: t('common.description'),
       component: 'InputTextArea',
-      componentProps: { rows: 5, placeholder: 'Please enter description' },
+      componentProps: { rows: 5 },
       ifShow: isCreate,
     },
   ];