Selaa lähdekoodia

```
feat(auth): 实现用户登录与认证功能优化

- 在 App.vue 中根据 token 控制用户信息展示及登录按钮显隐
- 新增获取用户信息、退出登录和更新用户信息接口
- 调整 request 拦截器逻辑,统一返回 response.data 并修正 token 存储字段为 'token'
- 登录弹框组件中完善短信验证码发送样式并自动填充测试手机号
- 引入 appStore 管理用户状态,并在登录成功后保存 token 和用户信息
- 页面加载时自动拉取用户信息,增强用户体验
```

zhangningning 1 viikko sitten
vanhempi
commit
04e9142e8b
5 muutettua tiedostoa jossa 85 lisäystä ja 18 poistoa
  1. 8 6
      src/App.vue
  2. 13 1
      src/api/auth.js
  3. 10 5
      src/api/request.js
  4. 15 3
      src/components/LoginDialog.vue
  5. 39 3
      src/pinia/appStore.js

+ 8 - 6
src/App.vue

@@ -15,9 +15,9 @@
           </el-menu>
           <div class="header-right">
             <el-avatar :size="32" :src="appStore.userInfo?.avatar || 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'" />
-            <el-dropdown>
+            <el-dropdown v-if="appStore.token">
               <span class="el-dropdown-link">
-                用户1
+                {{ appStore.userInfo?.nickName || '用户' }}
                 <el-icon class="el-icon--right">
                   <arrow-down />
                 </el-icon>
@@ -33,8 +33,7 @@
               </template>
             </el-dropdown>
             <!-- 打开登录弹框 -->
-            <el-button type="text" @click="openLoginDialog">登录</el-button>  
-            <el-button type="primary">注册</el-button>
+            <el-button type="text" @click="openLoginDialog" v-if="!appStore.token">登录</el-button>  
             <LangSwitch />
           </div>
         </div>
@@ -59,7 +58,7 @@
 
 <script setup>
 import LoginDialog from './components/LoginDialog.vue'
-import { computed,ref } from 'vue'
+import { computed,ref,onMounted } from 'vue'
 import LangSwitch from './components/LangSwitch.vue'
 import { ElConfigProvider } from 'element-plus'
 import { useRoute, useRouter } from 'vue-router'
@@ -77,7 +76,10 @@ const router = useRouter()
 
 // 登录弹框引用
 const loginDialogRef = ref(null)
-// 登录弹框显示状态
+
+onMounted(() => {
+  appStore.USERINFO()
+})
 
 // 打开登录弹框
 const openLoginDialog = () => {

+ 13 - 1
src/api/auth.js

@@ -18,10 +18,22 @@ export function loginEmail(data = {}) {
 }
 // 获取短信验证码
 export function getSmsCode(data = {}) {
-  console.log('getSmsCode',data)
+  console.log('getSmsCode1111',data)
   return request.get('/auth/sms-code',data)
 }
 // 获取邮箱验证码
 export function getEmailCode(data = {}) {
   return request.get('/auth/email-code',data)
 }
+// 获取用户信息
+export function getUserInfo(data = {}) {
+  return request.get('/auth/user/info',data)
+}
+// 退出登录
+export function logout(data = {}) {
+  return request.get('/auth/user/logout',data)
+}
+// 更新用户信息
+export function updateUserInfo(data = {}) {
+  return request.post('/auth/user/info/update',data)
+}

+ 10 - 5
src/api/request.js

@@ -14,7 +14,7 @@ const request = axios.create({
 request.interceptors.request.use(
   config => {
     // 获取 token(假设存储在 localStorage 中)
-    const token = localStorage.getItem('access_token')
+    const token = localStorage.getItem('token')
     if (token) {
       config.headers.Authorization = `Bearer ${token}`
     }
@@ -47,15 +47,15 @@ request.interceptors.response.use(
     
     // 假设 code 为 200 表示成功
     if (code === 200) {
-      return {code,data,msg}
+      return response.data
     } else if ([410000, 410001, 410002, 401, 403].includes(code)){
       localStorage.removeItem('access_token')
       window.location.href = '/login'
       
-      return {code,data,msg}
+      return response.data
     }else {
       ElMessage.error(msg+'response code:'+code || '请求失败')
-      return {code,data,msg}
+      return response.data
     }
   },
   error => {
@@ -157,4 +157,9 @@ export function del(url, params = {}, config = {}) {
   })
 }
 
-export default request
+export default {
+  get,
+  post,
+  put,
+  del
+}

+ 15 - 3
src/components/LoginDialog.vue

@@ -93,6 +93,7 @@
                 <el-button
                   :disabled="smsCountdown > 0"
                   @click="sendSmsCode"
+                  style="width:100px"
                   :class="{'countdown-btn': smsCountdown > 0}"
                   size="small"
                 >
@@ -153,6 +154,8 @@ import { ElMessage } from 'element-plus'
 import QQIcon from '@/assets/imgs/QQ.png'
 import WeChatIcon from '@/assets/imgs/WeChat.png'
 import { getCaptcha, loginUsername, loginPhone, loginEmail, getSmsCode, getEmailCode } from '@/api/auth.js'
+import { useAppStore } from '@/pinia/appStore'
+const appStore = useAppStore();
 // 正则表达式
 const PHONE_REGEX = /^1[3-9]\d{9}$/;
 const EMAIL_REGEX = /^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$/;
@@ -211,7 +214,7 @@ const passwordForm = reactive({
 
 // 短信登录表单
 const smsForm = reactive({
-  account: '',
+  account: '13925214105',
   verifyCode: ''
 })
 
@@ -345,7 +348,9 @@ const handlePasswordLogin = () => {
       if (res.code === 200) {
         ElMessage.success('登录成功')
         // emit('login-success', { type: 'password', userInfo: passwordForm })
-        dialogVisible.value = false
+        dialogVisible.value = false;
+        // 登录成功后,将token存储到localStorage
+        setToken(res.token);
       } else {
         ElMessage.error(res.msg || '登录失败')
       }
@@ -373,7 +378,10 @@ const handleSmsLogin = () => {
       if (res.code === 200) {
         ElMessage.success('登录成功')
         // emit('login-success', { type: 'sms', userInfo: smsForm })
-        dialogVisible.value = false
+        dialogVisible.value = false;
+        // 登录成功后,将token存储到localStorage
+        debugger
+        setToken(res.token);
       } else {
         ElMessage.error(res.msg || '登录失败')
       }
@@ -381,6 +389,10 @@ const handleSmsLogin = () => {
   })
 }
 
+const setToken = (token) => {
+  appStore.UPDATE_TOKEN(token);
+}
+
 
 // 微信登录
 const handleWechatLogin = () => {

+ 39 - 3
src/pinia/appStore.js

@@ -1,13 +1,49 @@
 import { defineStore } from 'pinia'
+import { getUserInfo,logout } from '@/api/auth.js'
 
 
 
-export const useAppStore = defineStore('lang', {
+export const useAppStore = defineStore('app', {
   state: () => ({
     // 当前语言
-    userInfo: localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : null
+    userInfo: localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : null,
+    token: localStorage.getItem('token') || null,
   }),
   actions: {
-   
+   UPDATE_TOKEN(token = '') {
+      if (!token) {
+        return;
+      }
+      this.token = token;
+      localStorage.setItem('token', token);
+      this.USERINFO();
+    },
+    LOGOUT() {
+      this.token = undefined;
+      this.userInfo = undefined;
+      localStorage.removeItem('token');
+      localStorage.removeItem('userInfo');
+    },
+    UPDATE_USERINFO(userInfo) {
+      this.userInfo = userInfo;
+      localStorage.setItem('userInfo', JSON.stringify(userInfo));
+      // uniLogin();
+    },
+     async USERINFO(force) {
+      try {
+        if (!this.token) {
+          return;
+        }
+        const res = await getUserInfo();
+        if (res.code === 200 && res.user) {
+          this.UPDATE_USERINFO(res.user);
+        }else {
+          this.LOGOUT();
+        }
+      } catch (e) {
+        // 可以处理异常
+      }
+    },
+
   }
 })