Selaa lähdekoodia

[Feature][UI Next] Add password page. (#7795)

songjianet 3 vuotta sitten
vanhempi
commit
5c57629781

+ 3 - 1
dolphinscheduler-ui-next/src/layouts/content/components/user/use-dropdown.ts

@@ -26,15 +26,17 @@ export function useDropDown() {
   const userStore = useUserStore()
 
   const handleSelect = (key: string | number, option: DropdownOption) => {
-    console.log(key, option)
     if (key === 'logout') {
       useLogout()
+    } else if (key === 'password') {
+      router.push({ path: 'password' })
     }
   }
 
   const useLogout = () => {
     logout().then(() => {
       userStore.setSessionId('')
+      userStore.setUserInfo({})
       router.push({ path: 'login' })
     })
   }

+ 7 - 1
dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts

@@ -41,6 +41,7 @@ import {
   SlackOutlined,
   EnvironmentOutlined,
   KeyOutlined,
+  SafetyOutlined,
 } from '@vicons/antd'
 
 export function useDataList() {
@@ -208,7 +209,7 @@ export function useDataList() {
         {
           label: t('menu.token_manage'),
           key: 'token-manage',
-          icon: renderIcon(KeyOutlined),
+          icon: renderIcon(SafetyOutlined),
         },
       ],
     },
@@ -231,6 +232,11 @@ export function useDataList() {
       key: 'profile',
       icon: renderIcon(UserOutlined),
     },
+    {
+      label: t('profile.password'),
+      key: 'password',
+      icon: renderIcon(KeyOutlined),
+    },
     {
       label: t('profile.logout'),
       key: 'logout',

+ 13 - 0
dolphinscheduler-ui-next/src/locales/modules/en_US.ts

@@ -31,6 +31,7 @@ const theme = {
 
 const profile = {
   profile: 'Profile',
+  password: 'Password',
   logout: 'Logout',
 }
 
@@ -76,10 +77,22 @@ const home = {
   state: 'State',
 }
 
+const password = {
+  edit_password: 'Edit Password',
+  password: 'Password',
+  confirm_password: 'Confirm Password',
+  password_tips: 'Please enter your password',
+  confirm_password_tips: 'Please enter your confirm password',
+  two_password_entries_are_inconsistent:
+    'Two Password Entries Are Inconsistent',
+  submit: 'Submit',
+}
+
 export default {
   login,
   theme,
   profile,
   menu,
   home,
+  password,
 }

+ 12 - 0
dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts

@@ -31,6 +31,7 @@ const theme = {
 
 const profile = {
   profile: '用户信息',
+  password: '密码管理',
   logout: '退出登录',
 }
 
@@ -76,10 +77,21 @@ const home = {
   state: '状态',
 }
 
+const password = {
+  edit_password: '修改密码',
+  password: '密码',
+  confirm_password: '确认密码',
+  password_tips: '请输入密码',
+  confirm_password_tips: '请输入确认密码',
+  two_password_entries_are_inconsistent: '两次密码输入不一致',
+  submit: '提交',
+}
+
 export default {
   login,
   theme,
   profile,
   menu,
   home,
+  password,
 }

+ 8 - 0
dolphinscheduler-ui-next/src/router/routes.ts

@@ -46,6 +46,14 @@ const basePage: RouteRecordRaw[] = [
           title: '首页',
         },
       },
+      {
+        path: '/password',
+        name: 'password',
+        component: components['password'],
+        meta: {
+          title: '修改密码',
+        },
+      },
     ],
   },
   projectsPage,

+ 10 - 0
dolphinscheduler-ui-next/src/service/modules/users/types.ts

@@ -88,6 +88,15 @@ interface RegisterUserReq {
   userPassword: string
 }
 
+interface UserInfoRes extends UserReq, IdReq {
+  userType: string
+  tenantCode?: any
+  queueName?: any
+  alertGroup?: any
+  createTime: string
+  updateTime: string
+}
+
 export {
   UserNameReq,
   UserNamesReq,
@@ -103,4 +112,5 @@ export {
   ListAllReq,
   ListReq,
   RegisterUserReq,
+  UserInfoRes,
 }

+ 4 - 1
dolphinscheduler-ui-next/src/store/user/types.ts

@@ -15,8 +15,11 @@
  * limitations under the License.
  */
 
+import type { UserInfoRes } from '@/service/modules/users/types'
+
 interface UserState {
   sessionId: string
+  userInfo: UserInfoRes | {}
 }
 
-export default UserState
+export { UserState }

+ 9 - 1
dolphinscheduler-ui-next/src/store/user/user.ts

@@ -16,22 +16,30 @@
  */
 
 import { defineStore } from 'pinia'
-import UserState from '@/store/user/types'
+import type { UserState } from '@/store/user/types'
+import type { UserInfoRes } from '@/service/modules/users/types'
 
 export const useUserStore = defineStore({
   id: 'user',
   state: (): UserState => ({
     sessionId: '',
+    userInfo: {},
   }),
   persist: true,
   getters: {
     getSessionId(): string {
       return this.sessionId
     },
+    getUserInfo(): UserInfoRes | {} {
+      return this.userInfo
+    },
   },
   actions: {
     setSessionId(sessionId: string): void {
       this.sessionId = sessionId
     },
+    setUserInfo(userInfo: UserInfoRes | {}): void {
+      this.userInfo = userInfo
+    },
   },
 })

+ 5 - 2
dolphinscheduler-ui-next/src/views/login/index.tsx

@@ -18,14 +18,14 @@
 import { defineComponent, toRefs, withKeys } from 'vue'
 import styles from './index.module.scss'
 import { NInput, NButton, NSwitch, NForm, NFormItem } from 'naive-ui'
-import { useValidate } from './use-validate'
+import { useForm } from './use-form'
 import { useTranslate } from './use-translate'
 import { useLogin } from './use-login'
 
 const login = defineComponent({
   name: 'login',
   setup() {
-    const { state, t, locale } = useValidate()
+    const { state, t, locale } = useForm()
 
     const { handleChange } = useTranslate(locale)
 
@@ -85,6 +85,9 @@ const login = defineComponent({
             <NButton
               round
               type='info'
+              disabled={
+                !this.loginForm.userName || !this.loginForm.userPassword
+              }
               style={{ width: '100%' }}
               onClick={this.handleLogin}
             >

+ 4 - 4
dolphinscheduler-ui-next/src/views/login/use-validate.ts

@@ -16,10 +16,10 @@
  */
 
 import { reactive, ref } from 'vue'
-import { FormRules } from 'naive-ui'
 import { useI18n } from 'vue-i18n'
+import type { FormRules } from 'naive-ui'
 
-export function useValidate() {
+export function useForm() {
   const { t, locale } = useI18n()
 
   const state = reactive({
@@ -33,7 +33,7 @@ export function useValidate() {
         trigger: ['input', 'blur'],
         validator() {
           if (state.loginForm.userName === '') {
-            return new Error(`${t('login.userName_tips')}`)
+            return new Error(t('login.userName_tips'))
           }
         },
       },
@@ -41,7 +41,7 @@ export function useValidate() {
         trigger: ['input', 'blur'],
         validator() {
           if (state.loginForm.userPassword === '') {
-            return new Error(`${t('login.userPassword_tips')}`)
+            return new Error(t('login.userPassword_tips'))
           }
         },
       },

+ 11 - 6
dolphinscheduler-ui-next/src/views/login/use-login.ts

@@ -17,21 +17,26 @@
 
 import { useRouter } from 'vue-router'
 import { login } from '@/service/modules/login'
+import { getUserInfo } from '@/service/modules/users'
 import { useUserStore } from '@/store/user/user'
-import { SessionIdRes } from '@/service/modules/login/types'
 import type { Router } from 'vue-router'
+import type { SessionIdRes } from '@/service/modules/login/types'
+import type { UserInfoRes } from '@/service/modules/users/types'
 
 export function useLogin(state: any) {
   const router: Router = useRouter()
   const userStore = useUserStore()
 
   const handleLogin = () => {
-    state.loginFormRef.validate((valid: any) => {
+    state.loginFormRef.validate(async (valid: any) => {
       if (!valid) {
-        login({ ...state.loginForm }).then((res: SessionIdRes) => {
-          userStore.setSessionId(res.sessionId)
-          router.push({ path: 'home' })
-        })
+        const loginRes: SessionIdRes = await login({ ...state.loginForm })
+        const userInfoRes: UserInfoRes = await getUserInfo()
+
+        await userStore.setSessionId(loginRes.sessionId)
+        await userStore.setUserInfo(userInfoRes)
+
+        router.push({ path: 'home' })
       }
     })
   }

+ 77 - 0
dolphinscheduler-ui-next/src/views/password/index.tsx

@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineComponent, toRefs } from 'vue'
+import { NForm, NFormItem, NButton, NInput } from 'naive-ui'
+import { useForm } from './use-form'
+import Card from '@/components/card'
+
+const password = defineComponent({
+  name: 'password',
+  setup() {
+    const { state, t } = useForm()
+
+    return { ...toRefs(state), t }
+  },
+  render() {
+    const { rules, passwordForm, t, handlePasswordInput } = this
+
+    return (
+      <Card title={t('password.edit_password')}>
+        {{
+          default: () => (
+            <div>
+              <NForm rules={rules} ref='passwordFormRef'>
+                <NFormItem label={t('password.password')} path='password'>
+                  <NInput
+                    type='password'
+                    placeholder={t('password.password_tips')}
+                    v-model={[passwordForm.password, 'value']}
+                    onInput={handlePasswordInput}
+                  />
+                </NFormItem>
+                <NFormItem
+                  label={t('password.confirm_password')}
+                  path='confirmPassword'
+                  ref='confirmPasswordItemFormRef'
+                >
+                  <NInput
+                    type='password'
+                    placeholder={t('password.confirm_password_tips')}
+                    v-model={[passwordForm.confirmPassword, 'value']}
+                  />
+                </NFormItem>
+              </NForm>
+              <NButton
+                disabled={
+                  !passwordForm.password ||
+                  !passwordForm.confirmPassword ||
+                  passwordForm.password !== passwordForm.confirmPassword
+                }
+                type='info'
+              >
+                {t('password.submit')}
+              </NButton>
+            </div>
+          ),
+        }}
+      </Card>
+    )
+  },
+})
+
+export default password

+ 73 - 0
dolphinscheduler-ui-next/src/views/password/use-form.ts

@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { reactive, ref } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { FormRules } from 'naive-ui'
+
+export function useForm() {
+  const { t } = useI18n()
+
+  const state = reactive({
+    passwordFormRef: ref(),
+    confirmPasswordItemFormRef: ref(),
+    passwordForm: {
+      password: '',
+      confirmPassword: '',
+    },
+    rules: {
+      password: {
+        required: true,
+        message: t('password.password_tips'),
+      },
+      confirmPassword: [
+        {
+          required: true,
+          message: t('password.confirm_password_tips'),
+        },
+        {
+          trigger: ['input'],
+          message: t('password.two_password_entries_are_inconsistent'),
+          validator: (rule: any, value: string): any => {
+            return (
+              state.passwordForm.password &&
+              state.passwordForm.password.startsWith(value) &&
+              state.passwordForm.password.length >= value.length
+            )
+          },
+        },
+        {
+          trigger: ['blur', 'password-input'],
+          message: t('password.two_password_entries_are_inconsistent'),
+          validator: (rule: any, value: string): any => {
+            return state.passwordForm.password === value
+          },
+        },
+      ],
+    } as FormRules,
+
+    handlePasswordInput: () => {
+      if (state.passwordForm.confirmPassword) {
+        state.confirmPasswordItemFormRef.value.validate({
+          trigger: 'password-input',
+        })
+      }
+    },
+  })
+
+  return { state, t }
+}