Bladeren bron

退出登录

panhui 2 jaren geleden
bovenliggende
commit
46d1a2418f

+ 1 - 1
src/components/common/LoginForm/index.vue

@@ -4,7 +4,7 @@
             <n-form-item ref="phoneRef" path="phone" label="">
                 <n-input v-model:value="form.phone" placeholder="请输入手机号" :allow-input="onlyAllowNumber">
                     <template #prefix>
-                        <n-icon size="24" class="text-gray-900 dark:text-gray-50 mr-3">
+                        <n-icon size="24" class="input-icon mr-3">
                             <user />
                         </n-icon>
                     </template>

+ 29 - 6
src/components/common/Setting/General.vue

@@ -1,12 +1,13 @@
 <script lang="ts" setup>
 import { computed, ref } from 'vue'
-import { NButton, NInput, NPopconfirm, NSelect, useMessage } from 'naive-ui'
+import { NButton, NInput, NPopconfirm, NSelect, useMessage, useDialog } from 'naive-ui'
 import type { Language, Theme } from '@/store/modules/app/helper'
 import { SvgIcon } from '@/components/common'
 import { useAppStore, useUserStore } from '@/store'
 import type { UserInfo } from '@/store/modules/user/helper'
 import { getCurrentDate } from '@/utils/functions'
 import { useBasicLayout } from '@/hooks/useBasicLayout'
+import { useRouter } from 'vue-router'
 import { t } from '@/locales'
 
 const appStore = useAppStore()
@@ -70,6 +71,24 @@ function handleReset() {
     window.location.reload()
 }
 
+const router = useRouter()
+const dialog = useDialog()
+const message = useMessage()
+function handleLogout() {
+    dialog.create({
+        title: '提示',
+        content: '确认要退出登录吗?',
+        positiveText: '退出登录',
+        negativeText: '取消',
+        maskClosable: false,
+        onPositiveClick: () => {
+            userStore.logout()
+            message.success('退出登录成功')
+            router.replace('/home')
+        }
+    })
+}
+
 function exportData(): void {
     const date = getCurrentDate()
     const data: string = localStorage.getItem('chatStorage') || '{}'
@@ -119,7 +138,7 @@ function handleImportButtonClick(): void {
 <template>
     <div class="p-4 space-y-5 min-h-[200px]">
         <div class="space-y-6">
-            <div class="flex items-center space-x-4">
+            <!-- <div class="flex items-center space-x-4">
                 <span class="flex-shrink-0 w-[100px]">{{ $t('setting.avatarLink') }}</span>
                 <div class="flex-1">
                     <NInput v-model:value="avatar" placeholder="" />
@@ -145,7 +164,7 @@ function handleImportButtonClick(): void {
                 <NButton size="tiny" text type="primary" @click="updateUserInfo({ description })">
                     {{ $t('common.save') }}
                 </NButton>
-            </div>
+            </div> -->
             <div class="flex items-center space-x-4" :class="isMobile && 'items-start'">
                 <span class="flex-shrink-0 w-[100px]">{{ $t('setting.chatHistory') }}</span>
 
@@ -194,7 +213,7 @@ function handleImportButtonClick(): void {
                     </template>
                 </div>
             </div>
-            <div class="flex items-center space-x-4">
+            <!-- <div class="flex items-center space-x-4">
                 <span class="flex-shrink-0 w-[100px]">{{ $t('setting.language') }}</span>
                 <div class="flex flex-wrap items-center gap-4">
                     <NSelect
@@ -204,12 +223,16 @@ function handleImportButtonClick(): void {
                         @update-value="value => appStore.setLanguage(value)"
                     />
                 </div>
-            </div>
-            <div class="flex items-center space-x-4">
+            </div> -->
+            <!-- <div class="flex items-center space-x-4">
                 <span class="flex-shrink-0 w-[100px]">{{ $t('setting.resetUserInfo') }}</span>
                 <NButton size="small" @click="handleReset">
                     {{ $t('common.reset') }}
                 </NButton>
+            </div> -->
+            <div class="flex items-center space-x-4">
+                <span class="flex-shrink-0 w-[100px]">退出登录</span>
+                <NButton size="small" @click="handleLogout"> 退出登录 </NButton>
             </div>
         </div>
     </div>

+ 1 - 1
src/components/common/Setting/index.vue

@@ -36,7 +36,7 @@ const show = computed({
 </script>
 
 <template>
-    <NModal v-model:show="show" :auto-focus="false" preset="card" style="width: 95%; max-width: 640px">
+    <NModal v-model:show="show" :auto-focus="false" preset="card" style="width: 90%; max-width: 640px">
         <div>
             <NTabs v-model:value="active" type="line" animated>
                 <NTabPane name="General" tab="General">

+ 1 - 0
src/components/common/Share/index.vue

@@ -90,6 +90,7 @@ defineExpose({ init })
 .share-box {
     .f-col();
     align-items: center;
+    --n-box-shadow: none;
 }
 
 .tips {

+ 5 - 1
src/components/common/UserAvatar/index.vue

@@ -13,6 +13,10 @@ const props = defineProps({
     avatarType: {
         type: String,
         default: 'default'
+    },
+    onlyAvatar: {
+        type: Boolean,
+        default: false
     }
 })
 </script>
@@ -27,7 +31,7 @@ const props = defineProps({
                 <NAvatar size="large" round :src="defaultAvatar" />
             </template>
         </div>
-        <div class="flex-1 min-w-0 ml-2" v-if="props.avatarType !== 'small'" :class="[avatarType + '-text']">
+        <div class="flex-1 min-w-0 ml-2" v-if="!onlyAvatar" :class="[avatarType + '-text']">
             <h2 class="overflow-hidden font-bold text-md text-ellipsis whitespace-nowrap">
                 {{ userInfo.name ?? 'ChenZhaoYu' }}
             </h2>

+ 7 - 0
src/store/modules/user/index.ts

@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
 import type { UserInfo, UserState } from './helper'
 import { defaultSetting, getLocalState, setLocalState } from './helper'
 import { fetchMy } from '@/api'
+import { useAuthStore } from '../auth'
 
 export const useUserStore = defineStore('user-store', {
     state: (): UserState => getLocalState(),
@@ -23,6 +24,12 @@ export const useUserStore = defineStore('user-store', {
         async fetch() {
             const data = await fetchMy<UserInfo>()
             this.setUserInfo(data)
+        },
+
+        logout() {
+            this.resetUserInfo()
+            useAuthStore().removeToken()
+            
         }
     }
 })

+ 11 - 1
src/views/chat/layout/sider/Footer.vue

@@ -1,16 +1,26 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from 'vue'
 import { HoverButton, SvgIcon, UserAvatar } from '@/components/common'
+import { useRouter } from 'vue-router'
 
 const Setting = defineAsyncComponent(() => import('@/components/common/Setting/index.vue'))
 
 const show = ref(false)
+
+const router = useRouter()
+function goMine() {
+    router.push({
+        name: 'mine'
+    })
+}
 </script>
 
 <template>
     <footer class="flex items-center justify-between min-w-0 p-4 overflow-hidden border-t dark:border-neutral-800">
         <div class="flex-1 flex-shrink-0 overflow-hidden">
-            <UserAvatar />
+            <n-button text @click="goMine">
+                <UserAvatar />
+            </n-button>
         </div>
 
         <HoverButton @click="show = true">

+ 41 - 3
src/views/page/Home.vue

@@ -12,10 +12,23 @@
             </template>
             <template #extra>
                 <div class="flex items-center py-3 lg:py-8 pr-4 lg:pr-52">
-                    <user-avatar avatarType="small" v-if="isLogin" />
+                    <template v-if="isLogin">
+                        <n-button text v-if="isMobile" @click="goMine">
+                            <user-avatar avatarType="small" onlyAvatar />
+                        </n-button>
+                        <n-popover placement="bottom" trigger="click" v-else>
+                            <template #trigger>
+                                <n-button text>
+                                    <user-avatar :avatarType="isMobile ? 'small' : 'default'" onlyAvatar />
+                                </n-button>
+                            </template>
+                            <n-button size="small" @click="logout" text>退出登录</n-button>
+                        </n-popover>
+                    </template>
+
                     <template v-else>
                         <n-button v-if="!isMobile" type="primary" round @click="showLogin = true"> 登录 </n-button>
-                        <n-button v-else @click="$router.push('/login')">登录</n-button>
+                        <n-button v-else @click="$router.push('/login')" quaternary type="primary">登录</n-button>
                     </template>
                 </div>
             </template>
@@ -113,7 +126,10 @@ import {
     NModal,
     NConfigProvider,
     darkTheme,
-    NEl
+    NEl,
+    NPopover,
+    useMessage,
+    useDialog
 } from 'naive-ui'
 import h5Bg from '@/assets/bg_mobile.jpg'
 import pcBg from '@/assets/bg_desktop.jpg'
@@ -194,6 +210,28 @@ function goChat() {
         router.push({ name: 'Chat' })
     }
 }
+
+function goMine() {
+    router.push({
+        name: 'mine'
+    })
+}
+
+const dialog = useDialog()
+const message = useMessage()
+function logout() {
+    dialog.create({
+        title: '提示',
+        content: '确认要退出登录吗?',
+        positiveText: '退出登录',
+        negativeText: '取消',
+        maskClosable: false,
+        onPositiveClick: () => {
+            userStore.logout()
+            message.success('退出登录成功')
+        }
+    })
+}
 </script>
 
 <style lang="less" scoped>

+ 30 - 2
src/views/page/Mine.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="page">
+    <div class="page h-full flex flex-col">
         <n-page-header title="个人中心" @back="handleBack"> </n-page-header>
         <n-card :bordered="false">
             <UserAvatar avatarType="large" />
@@ -30,15 +30,22 @@
             </n-row>
         </n-card>
 
+        <div class="flex-1"></div>
+
+        <div class="logout">
+            <n-button @click="logout" quaternary type="primary" block round size="large"> 退出登录 </n-button>
+        </div>
+
         <share ref="shareRef" />
     </div>
 </template>
 
 <script setup lang="ts">
 import { UserAvatar, VipCard, Share } from '@/components/common'
-import { NCard, NEl, NPageHeader, NRow, NCol, useMessage } from 'naive-ui'
+import { NCard, NEl, NPageHeader, NRow, NCol, useMessage, NButton, useDialog } from 'naive-ui'
 import { useRouter } from 'vue-router'
 import { ref } from 'vue'
+import { useUserStore } from '@/store'
 
 const router = useRouter()
 function handleBack() {
@@ -55,6 +62,23 @@ const shareRef: any = ref(null)
 function shareEvent() {
     shareRef.value.init()
 }
+
+const dialog = useDialog()
+const userStore = useUserStore()
+function logout() {
+    dialog.create({
+        title: '提示',
+        content: '确认要退出登录吗?',
+        positiveText: '退出登录',
+        negativeText: '取消',
+        maskClosable: false,
+        onPositiveClick: () => {
+            userStore.logout()
+            message.success('退出登录成功')
+            router.replace('/home')
+        }
+    })
+}
 </script>
 
 <style lang="less" scoped>
@@ -130,4 +154,8 @@ function shareEvent() {
         }
     }
 }
+
+.logout {
+    padding: 0 20px 50px;
+}
 </style>