|
|
|
@ -3,7 +3,12 @@
|
|
|
|
|
<div class="left-container">
|
|
|
|
|
<div class="user-info-card">
|
|
|
|
|
<div class="user-avatar">
|
|
|
|
|
<img :src="userInfo.avatar" alt="用户头像" />
|
|
|
|
|
<img
|
|
|
|
|
:src="userInfo.avatar || defaultAvatar"
|
|
|
|
|
:onerror="handleAvatarError"
|
|
|
|
|
alt="用户头像"
|
|
|
|
|
class="avatar"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="user-details">
|
|
|
|
|
<h2 class="username">{{ userInfo.username }}</h2>
|
|
|
|
@ -13,8 +18,16 @@
|
|
|
|
|
<span class="info-icon"><i class="el-icon-school"></i></span>
|
|
|
|
|
<span class="info-label">学院:</span>
|
|
|
|
|
<span class="info-value">{{ userInfo.college || '未设置' }}</span>
|
|
|
|
|
<el-switch
|
|
|
|
|
v-if="isCurrentUser"
|
|
|
|
|
v-model="privacySettings.showCollege"
|
|
|
|
|
active-text="公开"
|
|
|
|
|
inactive-text="隐藏"
|
|
|
|
|
@change="updatePrivacy"
|
|
|
|
|
class="privacy-switch"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="user-info-item">
|
|
|
|
|
<div class="user-info-item" v-if="isCurrentUser || privacySettings.showGender">
|
|
|
|
|
<span class="info-icon"><i class="el-icon-user"></i></span>
|
|
|
|
|
<span class="info-label">性别:</span>
|
|
|
|
|
<span class="info-value">
|
|
|
|
@ -22,43 +35,40 @@
|
|
|
|
|
<span v-else-if="userInfo.gender === 2">女</span>
|
|
|
|
|
<span v-else>未知</span>
|
|
|
|
|
</span>
|
|
|
|
|
<el-switch
|
|
|
|
|
v-if="isCurrentUser"
|
|
|
|
|
v-model="privacySettings.showGender"
|
|
|
|
|
active-text="公开"
|
|
|
|
|
inactive-text="隐藏"
|
|
|
|
|
@change="updatePrivacy"
|
|
|
|
|
class="privacy-switch"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="user-info-item" v-if="userInfo.phone && (isCurrentUser || privacySettings.showPhone)">
|
|
|
|
|
<span class="info-icon"><i class="el-icon-phone"></i></span>
|
|
|
|
|
<span class="info-label">电话:</span>
|
|
|
|
|
<span class="info-value">{{ userInfo.phone || '未设置' }}</span>
|
|
|
|
|
<el-switch
|
|
|
|
|
v-if="isCurrentUser"
|
|
|
|
|
v-model="privacySettings.showPhone"
|
|
|
|
|
active-text="公开"
|
|
|
|
|
inactive-text="隐藏"
|
|
|
|
|
@change="updatePrivacy"
|
|
|
|
|
class="privacy-switch"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="user-info-item" v-if="userInfo.email && (isCurrentUser || privacySettings.showEmail)">
|
|
|
|
|
<span class="info-icon"><i class="el-icon-message"></i></span>
|
|
|
|
|
<span class="info-label">邮箱:</span>
|
|
|
|
|
<span class="info-value">{{ userInfo.email || '未设置' }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="user-info-item" v-if="isCurrentUser">
|
|
|
|
|
<span class="info-icon"><i class="el-icon-lock"></i></span>
|
|
|
|
|
<span class="info-label">隐私设置:</span>
|
|
|
|
|
<div class="privacy-toggles">
|
|
|
|
|
<el-switch
|
|
|
|
|
v-model="privacySettings.showPhone"
|
|
|
|
|
active-text="电话"
|
|
|
|
|
inactive-text="电话"
|
|
|
|
|
@change="updatePrivacy"
|
|
|
|
|
class="privacy-switch"
|
|
|
|
|
/>
|
|
|
|
|
<el-switch
|
|
|
|
|
v-model="privacySettings.showEmail"
|
|
|
|
|
active-text="邮箱"
|
|
|
|
|
inactive-text="邮箱"
|
|
|
|
|
@change="updatePrivacy"
|
|
|
|
|
class="privacy-switch"
|
|
|
|
|
/>
|
|
|
|
|
<el-switch
|
|
|
|
|
v-model="privacySettings.showCollege"
|
|
|
|
|
active-text="学院"
|
|
|
|
|
inactive-text="学院"
|
|
|
|
|
@change="updatePrivacy"
|
|
|
|
|
class="privacy-switch"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<el-switch
|
|
|
|
|
v-if="isCurrentUser"
|
|
|
|
|
v-model="privacySettings.showEmail"
|
|
|
|
|
active-text="公开"
|
|
|
|
|
inactive-text="隐藏"
|
|
|
|
|
@change="updatePrivacy"
|
|
|
|
|
class="privacy-switch"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
@ -155,7 +165,8 @@
|
|
|
|
|
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue';
|
|
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
|
|
import { useUserStore } from '@/stores/user.js';
|
|
|
|
|
import axios from 'axios';
|
|
|
|
|
import request from '@/utils/request';
|
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const route = useRoute();
|
|
|
|
@ -192,18 +203,49 @@ const isFollowing = ref(false);
|
|
|
|
|
const privacySettings = ref({
|
|
|
|
|
showPhone: true,
|
|
|
|
|
showEmail: true,
|
|
|
|
|
showCollege: true
|
|
|
|
|
showCollege: true,
|
|
|
|
|
showGender: true
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 推荐用户
|
|
|
|
|
const recommendations = ref([]);
|
|
|
|
|
|
|
|
|
|
// 默认头像
|
|
|
|
|
const defaultAvatar = require('@/assets/default-avatar/boy_4.png');
|
|
|
|
|
|
|
|
|
|
// 处理头像加载错误
|
|
|
|
|
const handleAvatarError = "this.onerror=null;this.src='" + defaultAvatar + "'";
|
|
|
|
|
|
|
|
|
|
// 加载用户信息
|
|
|
|
|
const loadUserInfo = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(`/api/user/detail?id=${userId.value}`);
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
|
|
userInfo.value = response.data.data;
|
|
|
|
|
// 如果是当前用户,先从localStorage恢复基本信息
|
|
|
|
|
if (isCurrentUser.value) {
|
|
|
|
|
const storedUsername = localStorage.getItem('username');
|
|
|
|
|
const storedAvatar = localStorage.getItem('avatar');
|
|
|
|
|
|
|
|
|
|
if (storedUsername) {
|
|
|
|
|
userInfo.value = {
|
|
|
|
|
username: storedUsername,
|
|
|
|
|
avatar: storedAvatar || '',
|
|
|
|
|
role: localStorage.getItem('role') || 1,
|
|
|
|
|
userId: localStorage.getItem('userId')
|
|
|
|
|
};
|
|
|
|
|
console.log('从localStorage恢复用户基本信息:', storedUsername);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 使用正确的API路径获取用户信息
|
|
|
|
|
const response = await request.get('/user/info/getuserinfo', {
|
|
|
|
|
params: { userId: userId.value },
|
|
|
|
|
// 设置超时,避免长时间等待
|
|
|
|
|
timeout: 5000
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('获取用户信息响应:', response);
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
userInfo.value = response.data;
|
|
|
|
|
console.log('加载到的用户信息:', userInfo.value);
|
|
|
|
|
|
|
|
|
|
// 加载隐私设置
|
|
|
|
|
if (isCurrentUser.value) {
|
|
|
|
@ -212,6 +254,22 @@ const loadUserInfo = async () => {
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载用户信息失败:', error);
|
|
|
|
|
|
|
|
|
|
// 如果是网络错误,但已经从localStorage恢复了基本信息,则继续使用
|
|
|
|
|
if ((!error.response || error.code === 'ECONNABORTED') && userInfo.value.username) {
|
|
|
|
|
console.log('网络错误,但已恢复基本用户信息,继续使用');
|
|
|
|
|
// 不做处理,继续使用已恢复的信息
|
|
|
|
|
} else if (isCurrentUser.value) {
|
|
|
|
|
// 如果是当前用户但未能恢复信息,尝试从userStore获取
|
|
|
|
|
userInfo.value = {
|
|
|
|
|
username: userStore.userInfo.username || '用户',
|
|
|
|
|
avatar: userStore.userInfo.avatar || '',
|
|
|
|
|
userId: userStore.userInfo.userid
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
// 如果是查看其他用户但加载失败
|
|
|
|
|
ElMessage.warning('加载用户信息失败,请稍后再试');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -221,15 +279,15 @@ const loadUserPosts = async () => {
|
|
|
|
|
|
|
|
|
|
loading.value = true;
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get('/api/post/user', {
|
|
|
|
|
const response = await request.get('/post/user', {
|
|
|
|
|
params: {
|
|
|
|
|
userId: userId.value,
|
|
|
|
|
...pageParams
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
|
|
const newPosts = response.data.data.list || [];
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
const newPosts = response.data.list || [];
|
|
|
|
|
userPosts.value = [...userPosts.value, ...newPosts];
|
|
|
|
|
|
|
|
|
|
if (newPosts.length < pageParams.size) {
|
|
|
|
@ -255,9 +313,9 @@ const loadMorePosts = () => {
|
|
|
|
|
// 加载用户统计数据
|
|
|
|
|
const loadUserStats = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(`/api/user/stats?id=${userId.value}`);
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
|
|
userStats.value = response.data.data;
|
|
|
|
|
const response = await request.get('/user/stats', { params: { id: userId.value } });
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
userStats.value = response.data;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载用户统计数据失败:', error);
|
|
|
|
@ -268,9 +326,9 @@ const loadUserStats = async () => {
|
|
|
|
|
const checkFollowStatus = async () => {
|
|
|
|
|
if (!isCurrentUser.value && userStore.isLoggedIn) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(`/api/follow/check?followUserId=${userId.value}`);
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
|
|
isFollowing.value = response.data.data;
|
|
|
|
|
const response = await request.get('/follow/check', { params: { followUserId: userId.value } });
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
isFollowing.value = response.data;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('检查关注状态失败:', error);
|
|
|
|
@ -287,12 +345,12 @@ const toggleFollow = async () => {
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const url = isFollowing.value
|
|
|
|
|
? `/api/follow/cancel?followUserId=${userId.value}`
|
|
|
|
|
: `/api/follow/add?followUserId=${userId.value}`;
|
|
|
|
|
? '/follow/cancel'
|
|
|
|
|
: '/follow/add';
|
|
|
|
|
|
|
|
|
|
const response = await axios.post(url);
|
|
|
|
|
const response = await request.post(url, { followUserId: userId.value });
|
|
|
|
|
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
isFollowing.value = !isFollowing.value;
|
|
|
|
|
// 更新统计数据
|
|
|
|
|
loadUserStats();
|
|
|
|
@ -311,9 +369,9 @@ const openChat = () => {
|
|
|
|
|
// 加载隐私设置
|
|
|
|
|
const loadPrivacySettings = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get('/api/user/privacy');
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
|
|
privacySettings.value = response.data.data;
|
|
|
|
|
const response = await request.get('/user/privacy');
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
privacySettings.value = response.data;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载隐私设置失败:', error);
|
|
|
|
@ -323,7 +381,7 @@ const loadPrivacySettings = async () => {
|
|
|
|
|
// 更新隐私设置
|
|
|
|
|
const updatePrivacy = async () => {
|
|
|
|
|
try {
|
|
|
|
|
await axios.post('/api/user/privacy', privacySettings.value);
|
|
|
|
|
await request.post('/user/privacy', privacySettings.value);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('更新隐私设置失败:', error);
|
|
|
|
|
}
|
|
|
|
@ -334,12 +392,10 @@ const loadRecommendations = async () => {
|
|
|
|
|
if (!userStore.isLoggedIn) return;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get('/api/user/recommend', {
|
|
|
|
|
params: { limit: 5 }
|
|
|
|
|
});
|
|
|
|
|
const response = await request.get('/user/recommend', { params: { limit: 5 } });
|
|
|
|
|
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
|
|
recommendations.value = response.data.data || [];
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
recommendations.value = response.data || [];
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载推荐失败:', error);
|
|
|
|
@ -493,15 +549,8 @@ onUnmounted(() => {
|
|
|
|
|
color: #303133;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.privacy-toggles {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
margin-top: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.privacy-switch {
|
|
|
|
|
margin-right: 15px;
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.social-actions {
|
|
|
|
|