个人空间页部分完成By方丽彤

pull/1/head
helloworld180 2 months ago
parent a6b76ef7f3
commit e6ff388a9e

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

@ -4,6 +4,8 @@ import recommend from '@/views/recommend/index.vue'
import community from '@/views/community/trends.vue' import community from '@/views/community/trends.vue'
import chat from '@/views/chat/chat.vue' import chat from '@/views/chat/chat.vue'
import space from '@/views/space/space.vue' import space from '@/views/space/space.vue'
import informationPage from '@/views/space/informationPage.vue'
import familyTree from '@/views/space/familyTree.vue'
import {createRouter ,createWebHashHistory} from 'vue-router' import {createRouter ,createWebHashHistory} from 'vue-router'
@ -33,6 +35,14 @@ const routes = [
{ {
path:'space', path:'space',
component: space component: space
},
{
path:'informationPage',
component:informationPage
},
{
path:'familyTree',
component:familyTree
} }

@ -0,0 +1,150 @@
<template>
<div class="background">
<div class="tree">
<TreeChart :json="treeData">
<template v-slot:node="{ node }">
<div class="node-info">
<img :src="node.image_url" alt="image" class="node-image" />
<div class="info">
<div class="name">{{ node.name }}</div>
<button @click="toggleNode(node)">
{{ node.expanded ? '隐藏下一代' : '显示下一代' }}
</button>
</div>
</div>
<div v-if="node.expanded" class="children">
<!-- 子节点展示 -->
<TreeChart :json="node.children" v-if="node.children && node.children.length"/>
</div>
</template>
</TreeChart>
</div>
</div>
</template>
<script>
import TreeChart from "vue-tree-chart-3";
export default {
components: {
TreeChart
},
data() {
return {
treeData: {
name: '爸爸',
image_url: require('@/assets/pictures/space/Inbase.png'),
expanded: true, //
children: [
{
name: 'children1',
image_url: "https://static.refined-x.com/avat1.jpg",
expanded: true,
},
{
name: 'children2',
image_url: "https://static.refined-x.com/avat2.jpg",
expanded: true,
mate: [{
name: 'mate',
image_url: "https://static.refined-x.com/avat3.jpg"
}],
children: [
{
name: 'grandchild',
image_url: "https://static.refined-x.com/avat.jpg"
},
{
name: 'grandchild2',
image_url: "https://static.refined-x.com/avat1.jpg",
expanded: true,
children:[
{
name:'dd',
image_url: "https://static.refined-x.com/avat1.jpg",
}
]
},
{
name: 'grandchild3',
image_url: "https://static.refined-x.com/avat2.jpg"
},
{
name:'hh',
image_url: "https://static.refined-x.com/avat2.jpg"
}
]
},
{
name: 'children3',
image_url: "https://static.refined-x.com/avat.jpg"
}
]
}
};
},
methods: {
toggleNode(node) {
node.expanded = !node.expanded; // /
}
}
};
</script>
<style scoped>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.background {
display: flex;
align-content: center;
justify-content: center;
background-image: url("../../assets/pictures/space/Inbase3.png");
background-size: cover;
background-position: center top;
background-repeat: no-repeat;
height: 100vh;
width: 100%;
}
.tree {
display: flex;
position: absolute;
background: rgba(255, 255, 255, 0.8);
width: 1100px;
height: 700px;
border-radius: 30px;
margin-top: 30px;
margin-left: 240px;
padding-top: 100px;
justify-content: center;
align-items: center;
flex-shrink: 0;
}
.node-info {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.node-image {
width: 40px;
height: 40px;
border-radius: 50%;
margin-bottom: 10px;
}
.info {
font-size: 14px;
}
.children {
margin-top: 20px;
padding-left: 20px;
display: flex;
flex-direction: column;
}
</style>

@ -0,0 +1,216 @@
<template>
<div>
<!-- 个人资料 -->
<div class="base">
<div class="profile">
<h2>编辑简介</h2>
<div class="profile-content">
<!-- 头像 -->
<div class="avatar-container">
<img :src="user.avatar || defaultAvatar" alt="Avatar" class="avatar">
<!-- 编辑头像 -->
<label for="avatar-upload" class="edit-icon">
<input type="file" id="avatar-upload" @change="uploadImage" hidden>
</label>
</div>
<!-- 个人信息 -->
<div class="info">
<div class="column">
<label>账号</label>
<input type="text" v-model="user.account">
<label>邮箱</label>
<input type="email" v-model="user.email">
<label>生日</label>
<input type="date" v-model="user.birthday">
<label>职业</label>
<input type="text" v-model="user.job">
</div>
<div class="column">
<label>姓名</label>
<input type="text" v-model="user.name">
<label>密码</label>
<input type="password" v-model="user.password">
<label>居住地</label>
<input type="text" v-model="user.location">
<label>个人签名</label>
<input type="text" v-model="user.signature">
<!-- 保存按钮 -->
<button @click="saveProfile"></button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
user: {
avatar: '',
account: 'Charlene Reed',
email: 'charlenereed@gmail.com',
birthday: '1990-01-25',
job: 'San Jose, California, USA',
name: 'Charlene Reed',
password: '',
location: 'San Jose, California, USA',
signature: 'gali建帅 马思唯最好',
},
defaultAvatar: 'https://via.placeholder.com/150', //
};
},
methods: {
//
uploadImage(event) {
const file = event.target.files[0];
if (file) {
this.user.avatar = URL.createObjectURL(file);
}
},
//
async saveProfile() {
try {
//
const response = await axios.post('',null, {
params:{
avatar: this.user.avatar,
account: this.user.account,
email: this.user.email,
birthday: this.user.birthday,
job: this.user.job,
name: this.user.name,
password: this.user.password,
location: this.user.location,
signature: this.user.signature,
}
});
if (response.data.success) {
alert('个人信息已保存!');
} else {
alert('保存失败,请重试!');
}
} catch (error) {
console.error('保存时出错:', error);
alert('保存失败,请检查网络或稍后重试!');
}
},
},
};
</script>
<style scoped>
/* 个人资料 */
.base{
display: flex;
background-image: url("../../assets/pictures/space/Inbase.png");
background-size: 100%;
justify-content: center;
align-content: center;
height: 100vh;
padding:12px 200px;
}
.profile {
display: flex;
flex-direction: column;
background-color:rgba(255,255,255,0.8);
height: 600px;
width:930px;
border-radius: 50px;
margin: 20px;
}
.profile h2 {
position: relative;
display: inline-block;
margin-left: 48px;
margin-top: 32px;
font-size: 24px;
color: #FE4E96;
padding-bottom: 12px;
border-bottom:#F4F5F7 2px solid;
}
.profile h2::before{
content: '';
position: absolute;
bottom: 0;
left: -12px;
width: 124px;
border-bottom: #FEB2D7 4px solid;
}
.profile-content {
display: flex;
gap: 20px;
}
.avatar-container {
position: relative;
display: inline-block;
width: 140px;
height: 140px;
}
.avatar {
width: 100%;
height: 100%;
border-radius: 50%;
margin-left: 20px;
object-fit: cover;
background-color: #d3d3d3;
border: 2px solid #ccc;
}
.avatar-container input[type="file"]{
display: none;
}
.edit-icon {
position: absolute;
bottom: 0;
right: 0;
background-color: pink;
border-radius: 50%;
padding: 5px;
cursor: pointer;
}
.info {
display: flex;
margin-left: 70px;
gap: 20px;
}
.column {
display: flex;
flex-direction: column;
width: 256px;
gap: 20px;
padding-right: 80px;
}
.column input{
width: 116%;
height: 28px;
padding: 8px;
border-radius: 50px;
border: 1px solid #DFEAF2;
}
.column label {
display: block; /* 使标签独占一行 */
margin-bottom: -4px; /* 增加标签和输入框之间的间距 */
font-size: 14px; /* 可以调整字体大小 */
}
button {
display: flex;
flex-direction: row;
justify-content: center;
height: 40px;
width: 150px;
padding-top: 12px;
margin-left: 150px;
margin-top: 16px;
background-color:#F177A8;
color: #fff;
border: none;
border-radius: 50px;
cursor: pointer;
}
</style>

@ -1,9 +1,635 @@
<template> <template>
个人空间 <div class="container">
</template> <div class="content">
<script> <div class="profile-card">
export default { <!-- 头像 -->
name: 'spaceIndex', // <div class="avatar-section">
// <div class="avatar-container">
} <img :src="user.avatar || defaultAvatar" alt="Avatar" class="avatar">
</script> <!-- 更多信息按钮 -->
<button @click="showMoreInfo" class="showMoreInfo-btn">
<img src="../../assets/pictures/space/more.png" alt="">
</button>
<!-- 族谱树按钮 -->
<button @click="showFamilyTree" class="showFamilytree-btn">
<img src="../../assets/pictures/space/tree.png" alt="">
</button>
</div>
</div>
<!-- 基本信息 -->
<div class="user-info">
<h2>{{ userInfo.name || "加载中..." }}</h2>
<div class="info-container">
<p>
<img src="../../assets/pictures/space/map.png" style="width: 19px;">
{{ userInfo.location || "加载中..." }}
</p>
<p>
<img src="../../assets/pictures/space/calendar.png" style="width: 17px;">
{{ userInfo.joinedDate || "加载中..." }}
</p>
</div>
</div>
<!-- 兴趣爱好 / 择偶期望 / 职业 -->
<div class="interests">
<p>
<img src="../../assets/pictures/space/interest.png" alt="">
<span class="in-text">
<span class="title">兴趣爱好:</span>
<span class="text-content" id="interest">{{ userInfo.interests || "加载中..." }}</span>
</span>
</p>
<p>
<img src="../../assets/pictures/space/double.png" alt="">
<span class="in-text">
<span class="title">择偶期望:</span>
<span class="text-content" id="expectation">{{ userInfo.expectation || "加载中..." }}</span>
</span>
</p>
<p>
<img src="../../assets/pictures/space/career.png" alt="">
<span class="in-text">
<span class="title">职业:</span>
<span class="text-content" id="career">{{ userInfo.career || "加载中..." }}</span>
</span>
</p>
</div>
<!-- 操作按钮 -->
<div class="actions">
<button @click="editProfile"></button>
<button @click="privateChat"></button>
</div>
</div>
<div class="post-container">
<div class="heade">
<div class="left-header">
<span :class="{ 'active': selectedTab === 'all' }" @click="selectedTab = 'all'">全部</span>
<hr v-if="selectedTab === 'all'" />
</div>
<div class="right-header">家族故事</div>
</div>
<div class="post">
<div class="post-header">
<img src="../../assets/pictures/space/post1.png" alt="" />
<div class="post-info">
<h3>Devon Lane @johndue · 23s</h3>
<p>Tom is in a big hurry.</p>
</div>
</div>
<div class="post-img">
<img src="../../assets/pictures/space/post2.png" alt="" />
</div>
<div class="post-footer">
<div class="reactions">
<!-- 爱心图标用于点赞 -->
<div class="Like">
<span @click="increaseCount('like')" :class="{'liked': isLiked}">
<span v-if="isLiked"></span>
<span v-else>🤍</span>
</span>
{{ likeCount }}
</div>
<!-- 评论图标 -->
<div class="comment">
<span @click="increaseCount('comment')">
💬
</span>
{{ commentCount }}
</div>
</div>
<div class="comment-section">
<img src="../../assets/pictures/space/post1.png" alt="">
<input type="text" placeholder="Tweet your answer" />
<button class="answer-btn">Answer</button>
</div>
<div class="comments">
<div class="comment-item">
<img src="../../assets/pictures/space/post1.png" alt="Angela Arden's Profile Picture" />
<div class="comment-content">
<h4>Angela Arden @angela_arden</h4>
<p>Concordo...</p>
<div class="comment-actions">
<span class="comment">
<img src="../../assets/pictures/space/Vector.png" style="width: 16px;">
<span class="comment-count">2</span>
</span>
<span class="clockwise">
<img src="../../assets/pictures/space/ArrowsClockwise.png" style="width: 16px;">
<span class="clockwise-count">1</span>
</span>
<span class="like">
<img src="../../assets/pictures/space/Heart.png" style="width: 16px;">
<span class="like-count">3</span>
</span>
</div>
</div>
</div>
<div class="comment-item">
<img src="../../assets/pictures/space/post1.png" alt="Julia Stone's Profile Picture" />
<div class="comment-content">
<h4>Julia Stone @julia</h4>
<p>Olha, faz sentido!</p>
<div class="comment-actions">
<span class="comment">
<img src="../../assets/pictures/space/Vector.png" style="width: 16px;">
<span class="comment-count">2</span>
</span>
<span class="clockwise">
<img src="../../assets/pictures/space/ArrowsClockwise.png" style="width: 16px;">
<span class="clockwise-count">1</span>
</span>
<span class="like">
<img src="../../assets/pictures/space/Heart.png" style="width: 16px;">
<span class="like-count">3</span>
</span>
</div>
</div>
</div>
<div class="comment-item">
<img src="../../assets/pictures/space/post1.png" alt="Joey Tribiani's Profile Picture" />
<div class="comment-content">
<h4>Joey Tribiani @joey</h4>
<p>Parabéns pelo progresso!</p>
<div class="comment-actions">
<span class="comment">
<img src="../../assets/pictures/space/Vector.png" style="width: 16px;">
<span class="comment-count">2</span>
</span>
<span class="clockwise">
<img src="../../assets/pictures/space/ArrowsClockwise.png" style="width: 16px;">
<span class="clockwise-count">1</span>
</span>
<span class="like">
<img src="../../assets/pictures/space/Heart.png" style="width: 16px;">
<span class="like-count">3</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name:'spaceIndex',
data() {
return {
likeCount: 0,
isLiked:false,
commentCount:0,
user: {
avatar: "", // URL
},
userInfo: {
name: "", //
location: "", //
joinedDate: "", //
interests: "", //
expectation: "", //
career: "", //
},
defaultAvatar: "https://via.placeholder.com/150", //
};
},
methods: {
increaseCount(type){
if(type === 'like'){
if(this.isLiked){
this.likeCount--;
}else{
this.likeCount++;
}
this.isLiked=!this.isLiked;
}else if(type === 'comment'){
this.commentCount++;
}
},
async fetchUserInfo() {
try {
//
const response = await axios.get("/api/getUserInfo", {
params: {
userId: "12345", // ID
},
});
//
// {
// avatar: "https://example.com/avatar.jpg",
// name: "John Doe",
// location: "San Jose, California",
// joinedDate: "2021-01-01",
// interests: ", , ",
// expectation: "",
// career: ""
// }
//
this.user.avatar = response.data.avatar;
this.userInfo.name = response.data.name;
this.userInfo.location = response.data.location;
this.userInfo.joinedDate = response.data.joinedDate;
this.userInfo.interests = response.data.interests;
this.userInfo.expectation = response.data.expectation;
this.userInfo.career = response.data.career;
} catch (error) {
console.error("获取用户信息失败:", error);
alert("无法加载用户信息,请稍后重试!");
}
},
selectTab(tab) {
this.selectedTab = tab;
},
showMoreInfo() {
},
showFamilyTree() {
this.$router.push('/main/familyTree');
},
editProfile() {
this.$router.push('/main/informationPage'); // 使
},
privateChat() {
// Navigate to private chat page
}
},
mounted() {
//
this.fetchUserInfo();
},
};
</script>
<style scoped>
.content {
display: flex;
justify-content: space-between;
background-image: url("../../assets/pictures/space/Inbase2.png");
background-size: 100%;
height: 100vh;
padding: 20px;
}
.profile-card {
background-color: #FFFFFF;
padding: 20px;
border-radius: 30px;
margin-top: 70px;
margin-left: 40px;
width: 410px;
height: 540px;
border-top: 10px solid #9EAFFD;
position: relative; /* 为伪元素定位 */
}
.profile-card::before {
content: '';
position: absolute;
top: -10px; /* 使蓝色区域位于框外 */
left: 0;
right: 0;
height: 20px; /* 蓝色区域的高度 */
border-top-left-radius: 30px; /* 圆角与卡片的左上角对齐 */
border-top-right-radius: 30px; /* 圆角与卡片的右上角对齐 */
overflow: hidden;
}
.avatar-section {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.avatar-container {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.avatar {
margin-bottom: 20px;
width: 138px;
height: 138px;
border-radius: 50%;
}
.showMoreInfo-btn,
.showFamilytree-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 80px;
height: 80px;
border-radius: 50%; /* 圆形按钮 */
border: none;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); /* 添加阴影效果 */
}
.showMoreInfo-btn {
left: -130px; /* 在头像左侧 */
top: 110px;
}
.showFamilytree-btn {
right: -130px; /* 在头像右侧 */
top: 110px;
}
.user-info {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.user-info h2{
font-size: 21px;
margin-top: 8px;
font-weight: normal;
font-style: Italic;
white-space: nowrap; /* 防止文本换行 */
}
.info-container {
display: flex;
justify-content: center;
margin-top: -55px;
gap: 5px;
}
.user-info p{
margin-top: 40px;
display: flex;
flex-direction: row;
justify-content: center;
font-size: 14px;
white-space: nowrap;
}
.interests p{
display: flex;
flex-direction: row;
align-content: center;
margin-top: 4px;
}
.interests p img{
width: 44px;
height: 44px;
margin-top: 6px;
margin-left: 8px;
}
.interests p .in-text{
display: flex;
flex-direction: column;
gap: 10px;
}
.interests p .title{
margin-left: 12px;
margin-top: 10px;
font-size: 18px;
font-weight: bold;
white-space: nowrap;
}
.interests p .text-content{
font-size: 14px;
margin-left: 10px;
}
.actions button {
color:white;
font-size: 18px;
background-color: #f077a8;
padding: 10px 20px;
margin-left: 55px;
margin-right: 40px;
margin-top: 30px;
border: none;
border-radius: 30px;
width: 100px;
cursor: pointer;
}
.post-container {
font-family: Arial, sans-serif;
display: flex;
/* align-items: center; */
background: rgba(255, 255, 255, 0.8);
height: 620px;
margin: 30px auto;
border-radius: 30px;
width: 750px;
padding: 20px;
}
.heade{
display: flex;
justify-content: space-between;
align-content: center;
padding-left: 180px;
white-space: nowrap;
}
.left-header span {
cursor: pointer;
}
.left-header .active {
color: #1DA1F2;
}
.left-header hr {
border-color:#1DA1F2;
width: 100px;
margin-left: -32px;
margin-top: 5px;
}
.right-header {
padding-left: 280px;
}
.post {
margin-left: -600px;
margin-top: 200px;
border-radius: 10px;
margin-bottom: 20px;
}
.post-header {
display: flex;
margin-top:-160px;
margin-left: 30px;
padding: 10px;
position: relative;
}
.post-header img {
width: 56px;
height: 56px;
border-radius: 50%;
}
.post-info h3 {
margin-top:6px;
padding-left: 20px;
font-size: 14px;
font-weight: normal;
font-family: Italic;
font-style: ABeeZee;
white-space: nowrap;
}
.post-info p {
margin: 0;
font-size: 18px;
white-space: nowrap;
margin-left: 80px;
}
.post-img {
display: flex;
left: 220px;
width: 329px;
height: 163px;
position: relative;
}
.post-footer {
padding: 10px;
}
/* 图标的样式 */
.reactions span {
font-size: 24px;
cursor: pointer;
margin: 0 2px;
display: inline-block;
transition: transform 0.3s;
}
/* 点赞图标选中时的样式 */
.liked {
color: red; /* 红色表示已点赞 */
transform: scale(1.2); /* 点击时稍微放大 */
}
/* 图标悬停时的效果 */
.reactions span:hover {
transform: scale(1.1); /* 悬停时稍微放大 */
}
/* 增加点赞和评论数值的可读性 */
.reactions {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 20px;
padding: 0 10px;
}
.comment{
display: flex;
align-items: center;
margin-right: 70px;
}
.Like{
margin-left: 170px;
}
/* .reactions span img {
padding-left: 230px;
padding-top: 10px;
} */
.reactions .count {
font-size: 21px;
color: #666;
padding-left: 8px;
}
.comment-section {
display: flex;
align-items: center;
margin-bottom: 10px;
padding-left: 120px;
/* border-bottom: 1px solid #ccc; */
}
.comment-section img {
width: 46px;
padding-bottom: 10px;
padding-top: 10px;
}
.comment-section input {
flex: 1;
height: 40px;
width: 380px;
border-radius: 5px;
border: none;
font-size: 16px;
padding-left: 14px;
}
.answer-btn {
background-color: #f077a8;
color: white;
border: none;
border-radius: 50px;
padding: 5px 10px;
margin-right: -80px;
font-size: 15px;
cursor: pointer;
}
.comments {
padding-left: 120px;
max-height: 220px;
width: 550px;
overflow: auto;
}
.comment-item {
display: flex;
align-items: center;
border-top: 1px solid #ccc;
}
.comment-item img {
width: 46px;
border-radius: 50%;
margin-right: 10px;
padding-bottom: 10px;
}
.comment-content h4 {
margin: 0;
padding-top: 10px;
padding-bottom: 6px;
font-size: 12px;
}
.comment-content p {
margin: 0;
font-size: 12px;
color: #666;
}
.comment-actions {
display: flex;
justify-content: space-between;
align-content: center;
font-size: 12px;
color: #666;
}
.comment-actions span {
display: flex;
align-content: center;
padding-top: 10px;
padding-left: 5px;
}
.comment-actions span span{
padding-top: 2px;
}
</style>
Loading…
Cancel
Save