Browse Source

feat(auth): 添加通用注销功能并重构登出逻辑

- 在 useAuth 中新增支持配置的 logout 函数
- 支持确认弹窗、跳转链接、提示 Toast 和回调函数
- 多处页面组件引入并调用新版 logout 方法
- 统一处理清除本地存储和页面跳转行为
- 首页文案从“健康咨询”更改为“医生预约”
mcbaiyun 1 month ago
parent
commit
ce34a69658

+ 81 - 0
src/composables/useAuth.ts

@@ -43,3 +43,84 @@ export const authState = {
   logged: ref<boolean>(isLoggedIn()),
   role: ref<number | null>(getRole())
 }
+
+export type LogoutOptions = {
+  /** 是否先显示确认弹窗,默认 true */
+  confirm?: boolean
+  /** 注销后跳转的页面(默认回首页) */
+  redirectUrl?: string
+  /** 注销后是否显示 Toast(默认 true) */
+  showToast?: boolean
+  /** 注销后回调(可用于清理组件本地状态) */
+  after?: () => void
+}
+
+export async function logout(options: LogoutOptions = {}): Promise<boolean> {
+  const { confirm = true, redirectUrl = '/pages/public/index/index', showToast = true, after } = options
+
+  const doLogout = () => {
+    try {
+      // 清理常见的本地存储项
+      uni.removeStorageSync(tokenKey)
+      uni.removeStorageSync(roleKey)
+      try {
+        uni.removeStorageSync('user_info')
+      } catch (e) {
+        // ignore
+      }
+    } catch (err) {
+      console.error('logout: removeStorageSync error', err)
+    }
+    // 更新 reactives
+    try {
+      authState.logged.value = false
+      authState.role.value = null
+    } catch (e) {
+      // ignore
+    }
+
+    try {
+      if (showToast) uni.showToast({ title: '已退出登录', icon: 'none' })
+    } catch (e) {
+      // ignore
+    }
+
+    if (typeof after === 'function') {
+      try {
+        after()
+      } catch (e) {
+        console.error('logout: after callback error', e)
+      }
+    }
+
+    try {
+      // 使用 reLaunch 清空页面栈
+      if (redirectUrl) {
+        uni.reLaunch({ url: redirectUrl })
+      }
+    } catch (e) {
+      console.error('logout: reLaunch error', e)
+    }
+
+    return true
+  }
+
+  if (confirm) {
+    return new Promise((resolve) => {
+      uni.showModal({
+        title: '提示',
+        content: '确定要退出登录吗?',
+        success: (res) => {
+          if (res.confirm) {
+            doLogout()
+            resolve(true)
+            return
+          }
+          resolve(false)
+        }
+      })
+    })
+  }
+
+  return Promise.resolve(doLogout())
+}

+ 3 - 15
src/pages/doctor/profile/index.vue

@@ -46,7 +46,7 @@ import { onShow } from '@dcloudio/uni-app'
 import CustomNav from '@/components/custom-nav.vue'
 import { fetchUserInfo as fetchUserInfoApi, downloadAvatar as downloadAvatarApi } from '@/api/user'
 import TabBar from '@/components/tab-bar.vue'
-import { isLoggedIn as checkLogin, getRole } from '@/composables/useAuth'
+import { isLoggedIn as checkLogin, getRole, logout } from '@/composables/useAuth'
 
 const title = ref('个人中心')
 
@@ -159,20 +159,8 @@ const onMenuClick = (type: string) => {
   }
 }
 
-const onLogout = () => {
-  uni.showModal({
-    title: '提示',
-    content: '确定要退出登录吗?',
-    success: (res) => {
-      if (res.confirm) {
-        uni.removeStorageSync('token')
-        uni.removeStorageSync('role')
-        user.value = {}
-        uni.showToast({ title: '已退出登录', icon: 'none' })
-        uni.reLaunch({ url: '/pages/public/index/index' })
-      }
-    }
-  })
+const onLogout = async () => {
+  await logout({ after: () => { user.value = {} } })
 }
 </script>
 

+ 3 - 15
src/pages/patient-family/profile/index.vue

@@ -46,7 +46,7 @@ import { onShow } from '@dcloudio/uni-app'
 import CustomNav from '@/components/custom-nav.vue'
 import { fetchUserInfo as fetchUserInfoApi, downloadAvatar as downloadAvatarApi } from '@/api/user'
 import TabBar from '@/components/tab-bar.vue'
-import { isLoggedIn as checkLogin, getRole } from '@/composables/useAuth'
+import { isLoggedIn as checkLogin, getRole, logout } from '@/composables/useAuth'
 
 const title = ref('个人中心')
 
@@ -164,20 +164,8 @@ const onMenuClick = (type: string) => {
   }
 }
 
-const onLogout = () => {
-  uni.showModal({
-    title: '提示',
-    content: '确定要退出登录吗?',
-    success: (res) => {
-      if (res.confirm) {
-        uni.removeStorageSync('token')
-        uni.removeStorageSync('role')
-        user.value = {}
-        uni.showToast({ title: '已退出登录', icon: 'none' })
-        uni.reLaunch({ url: '/pages/public/index/index' })
-      }
-    }
-  })
+const onLogout = async () => {
+  await logout({ after: () => { user.value = {} } })
 }
 </script>
 

+ 3 - 14
src/pages/patient/profile/index.vue

@@ -49,6 +49,7 @@ import { computed } from 'vue'
 import { onShow } from '@dcloudio/uni-app'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
+import { logout } from '@/composables/useAuth'
 import { fetchUserInfo as fetchUserInfoApi, downloadAvatar as downloadAvatarApi } from '@/api/user'
 
 const title = ref('个人中心')
@@ -161,20 +162,8 @@ const onMenuClick = (type: string) => {
   })
 }
 
-const onLogout = () => {
-  uni.showModal({
-    title: '提示',
-    content: '确定要退出登录吗?',
-    success: (res) => {
-      if (res.confirm) {
-        uni.removeStorageSync('token')
-        uni.removeStorageSync('role')
-        user.value = {}
-        uni.showToast({ title: '已退出登录', icon: 'none' })
-        uni.reLaunch({ url: '/pages/public/index/index' })
-      }
-    }
-  })
+const onLogout = async () => {
+  await logout({ after: () => { user.value = {} } })
 }
 </script>
 

+ 1 - 1
src/pages/public/index/index.vue

@@ -35,7 +35,7 @@ const bannerImages = [
 const cards = [
   { title: '健康档案', desc: '管理您的健康信息' },
   { title: '慢病管理', desc: '查看慢病相关数据' },
-  { title: '健康咨询', desc: '在线咨询医生' },
+  { title: '医生预约', desc: '在线预约医生' },
   { title: '用药提醒', desc: '设置用药提醒' }
 ]
 

+ 4 - 15
src/pages/public/profile/index.vue

@@ -41,7 +41,7 @@ import { computed } from 'vue'
 import { onShow } from '@dcloudio/uni-app'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
-import { isLoggedIn as checkLogin, getRole } from '@/composables/useAuth'
+import { isLoggedIn as checkLogin, getRole, logout } from '@/composables/useAuth'
 import { fetchUserInfo as fetchUserInfoApi, downloadAvatar as downloadAvatarApi } from '@/api/user'
 
 const title = ref('个人中心')
@@ -151,20 +151,9 @@ const onMenuClick = (type: string) => {
   })
 }
 
-const onLogout = () => {
-  uni.showModal({
-    title: '提示',
-    content: '确定要退出登录吗?',
-    success: (res) => {
-      if (res.confirm) {
-        uni.removeStorageSync('token')
-        uni.removeStorageSync('role')
-        user.value = {}
-        uni.showToast({ title: '已退出登录', icon: 'none' })
-        uni.reLaunch({ url: '/pages/public/index/index' })
-      }
-    }
-  })
+const onLogout = async () => {
+  // 绑定到公共 logout:需要在退出后清空本地 user 状态
+  await logout({ after: () => { user.value = {} } })
 }
 </script>