Преглед на файлове

```
feat(avatar): 优化头像更新逻辑并完善用户信息获取流程

- 修改 Avatar.vue 中的 avatar-updated 事件处理函数为 handleAvatarUpdated,
支持接收新的头像 URL 并更新本地缓存
- 在 InfoDialog.vue 中增强 avatarUpdated 事件发射逻辑,支持传递头像 URL 参数
- 完善上传和保存头像时的数据同步机制,确保界面与数据一致性
- 登录成功后主动拉取完整用户信息(包含头像),并缓存至本地存储
- 增加对默认头像的判断,避免无效头像链接被保存
```

zhuli преди 2 седмици
родител
ревизия
d5135aa752
променени са 3 файла, в които са добавени 91 реда и са изтрити 6 реда
  1. 27 1
      src/layouts/components/Header/components/Avatar.vue
  2. 34 5
      src/layouts/components/Header/components/InfoDialog.vue
  3. 30 0
      src/views/login/index.vue

+ 27 - 1
src/layouts/components/Header/components/Avatar.vue

@@ -18,7 +18,7 @@
     </template>
   </el-dropdown>
   <!-- infoDialog -->
-  <InfoDialog ref="infoRef" @avatar-updated="getUserInfo" />
+  <InfoDialog ref="infoRef" @avatar-updated="handleAvatarUpdated" />
   <!-- passwordDialog -->
   <PasswordDialog ref="passwordRef" />
 </template>
@@ -66,10 +66,36 @@ const avatarUrl = computed(() => {
   return headImg.value && headImg.value !== null && headImg.value !== "" ? headImg.value : defaultAvatar;
 });
 
+// 处理头像更新事件
+const handleAvatarUpdated = async (newAvatarUrl?: string) => {
+  console.log("收到头像更新事件,新头像URL:", newAvatarUrl);
+  const userInfo = localGet("geeker-user")?.userInfo || {};
+  if (newAvatarUrl && newAvatarUrl.trim() !== "") {
+    // 如果传递了新的头像URL,直接更新
+    headImg.value = newAvatarUrl;
+    if (userInfo.phone) {
+      localSet(`avatar_${userInfo.phone}`, newAvatarUrl);
+      console.log("直接更新头像URL:", newAvatarUrl, "当前 headImg.value:", headImg.value);
+    }
+  } else {
+    // 如果没有传递URL或URL为空,则重新获取用户信息
+    console.log("头像URL为空,重新获取用户信息");
+    await getUserInfo();
+  }
+};
+
 // 获取用户信息
 const getUserInfo = async () => {
   const userInfo = localGet("geeker-user")?.userInfo || {};
   if (userInfo.phone) {
+    // 先检查登录时存储的用户信息中是否有头像
+    const loginAvatarUrl = userInfo.headImg || userInfo.avatar || "";
+    if (loginAvatarUrl && loginAvatarUrl.trim() !== "") {
+      headImg.value = loginAvatarUrl;
+      localSet(`avatar_${userInfo.phone}`, loginAvatarUrl);
+      console.log("从登录信息中获取头像URL:", loginAvatarUrl);
+    }
+
     try {
       const res: any = await getMerchantByPhone({ phone: userInfo.phone });
       console.log("API返回数据:", res);

+ 34 - 5
src/layouts/components/Header/components/InfoDialog.vue

@@ -52,7 +52,7 @@ import defaultAvatar from "@/assets/images/avatar.gif";
 import { head } from "lodash";
 
 const emit = defineEmits<{
-  avatarUpdated: [];
+  avatarUpdated: [avatarUrl?: string];
 }>();
 
 const userInfo = localGet("geeker-user")?.userInfo || {};
@@ -82,6 +82,7 @@ const getUserInfo = async () => {
     const headImg = res.data.headImg;
     if (headImg && headImg !== null && headImg !== "") {
       // 如果有头像,使用用户头像
+      headImg1.value = headImg; // 初始化 headImg1
       form.avatarList = [
         {
           name: "avatar",
@@ -91,6 +92,7 @@ const getUserInfo = async () => {
       ];
     } else {
       // 如果 headImg 为 null 或空,使用默认头像
+      headImg1.value = ""; // 清空 headImg1
       form.avatarList = [
         {
           name: "avatar",
@@ -115,6 +117,11 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
     const fileUrl = res?.data?.fileUrl || res?.data?.[0] || res?.fileUrl;
     if (fileUrl) {
       headImg1.value = fileUrl;
+      // 更新 form.avatarList 中对应文件的 URL
+      if (form.avatarList && form.avatarList.length > 0) {
+        form.avatarList[0].url = fileUrl;
+        form.avatarList[0].response = { fileUrl };
+      }
       // 调用 onSuccess 回调,传入响应数据
       options.onSuccess({ fileUrl });
     } else {
@@ -127,20 +134,42 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
 };
 const getSaveUserInfo = async () => {
   try {
+    // 获取头像URL:优先使用新上传的,否则从 avatarList 中获取,最后为空字符串
+    let avatarUrl = headImg1.value;
+    console.log("保存前 headImg1.value:", headImg1.value);
+    console.log("保存前 form.avatarList:", form.avatarList);
+
+    // 如果 headImg1.value 为空,尝试从 form.avatarList 中获取
+    if (!avatarUrl && form.avatarList && form.avatarList.length > 0) {
+      const avatarFile = form.avatarList[0];
+      // 从 file.url 或 file.response 中获取 URL
+      const fileUrl = avatarFile.url || (avatarFile.response as any)?.fileUrl || "";
+      // 排除默认头像
+      if (fileUrl && fileUrl !== defaultAvatar) {
+        avatarUrl = fileUrl;
+        // 同时更新 headImg1.value,以便后续使用
+        headImg1.value = fileUrl;
+      }
+    }
+
+    console.log("保存时使用的头像URL:", avatarUrl);
+
     const res: any = await updateMerchantUserInfo({
       id: userId.value,
       nickName: form.nickname,
-      headImg: headImg1.value ? headImg1.value : "",
+      headImg: avatarUrl || "",
       accountBlurb: form.intro
     });
 
     if (res.code == 200) {
       ElMessage.success(res.msg || "保存成功");
       dialogVisible.value = false;
-      // 可以刷新用户信息
+      // 通知父组件头像已更新,传递新的头像URL(优先使用保存的头像URL)
+      const finalAvatarUrl = avatarUrl && avatarUrl.trim() !== "" ? avatarUrl : res.data?.headImg || "";
+      console.log("保存成功,传递给父组件的头像URL:", finalAvatarUrl);
+      emit("avatarUpdated", finalAvatarUrl);
+      // 刷新用户信息(用于更新对话框中的数据)
       getUserInfo();
-      // 通知父组件头像已更新
-      emit("avatarUpdated");
     } else {
       ElMessage.error(res.msg || "保存失败,请重试");
     }

+ 30 - 0
src/views/login/index.vue

@@ -610,6 +610,7 @@ import {
   registerAccount,
   registerCheck
 } from "@/api/modules/newLoginApi";
+import { getMerchantByPhone } from "@/api/modules/homeEntry";
 import { localGet, localRemove, localSet } from "@/utils";
 import * as path from "node:path";
 import { checkMenuClickPermission } from "@/utils/permission";
@@ -929,6 +930,35 @@ const handleLogin = async () => {
         } else {
           localRemove("businessSection");
         }
+
+        // 登录成功后,立即获取完整的用户信息(包括头像)
+        if (res.data.phone) {
+          try {
+            const merchantRes: any = await getMerchantByPhone({ phone: res.data.phone });
+            if (merchantRes && merchantRes.code == 200 && merchantRes.data) {
+              // 更新用户信息到本地存储
+              const updatedUserInfo = {
+                ...userInfo,
+                userInfo: {
+                  ...userInfo.userInfo,
+                  ...merchantRes.data
+                }
+              };
+              localSet("geeker-user", updatedUserInfo);
+              userStore.setUserInfo(updatedUserInfo.userInfo);
+
+              // 如果有头像,缓存头像URL
+              const avatarUrl = merchantRes.data.headImg || merchantRes.data.avatar || "";
+              if (avatarUrl && avatarUrl.trim() !== "") {
+                localSet(`avatar_${res.data.phone}`, avatarUrl);
+              }
+            }
+          } catch (error) {
+            console.error("获取用户信息失败:", error);
+            // 即使获取失败,也不影响登录流程
+          }
+        }
+
         sessionStorage.removeItem("ticketManagement_activeName");
         await initDynamicRouter();