yunzer_go/frontend/src/views/user/profile/messages.vue

190 lines
3.8 KiB
Vue

<template>
<div class="content-section">
<div class="content-header">
<h2 class="content-title">我的消息</h2>
<p class="content-desc">查看系统消息和通知</p>
</div>
<div class="content-body">
<div v-if="messages.length === 0" class="empty-state">
<i class="fa-solid fa-message"></i>
<p>暂无消息</p>
</div>
<div v-else class="message-list">
<div
v-for="message in messages"
:key="message.id"
class="message-item"
:class="{ unread: !message.read }"
@click="markAsRead(message.id)"
>
<div class="message-icon">
<i :class="getMessageIcon(message.type)"></i>
</div>
<div class="message-content">
<div class="message-header">
<h4 class="message-title">{{ message.title }}</h4>
<span class="message-time">{{ message.time }}</span>
</div>
<p class="message-text">{{ message.content }}</p>
</div>
<div v-if="!message.read" class="unread-dot"></div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
interface Message {
id: string;
title: string;
content: string;
time: string;
type: "system" | "notification" | "warning";
read: boolean;
}
// 模拟数据
const messages = ref<Message[]>([]);
// 获取消息图标
const getMessageIcon = (type: string) => {
switch (type) {
case "system":
return "fa-solid fa-cog";
case "notification":
return "fa-solid fa-bell";
case "warning":
return "fa-solid fa-exclamation-triangle";
default:
return "fa-solid fa-info";
}
};
// 标记为已读
const markAsRead = (messageId: string) => {
const message = messages.value.find((m) => m.id === messageId);
if (message) {
message.read = true;
}
};
// 初始化数据
const initMessages = () => {
// 这里可以调用API获取消息数据
messages.value = [];
};
onMounted(() => {
initMessages();
});
</script>
<style lang="less" scoped>
.message-list {
.message-item {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 16px;
border: 1px solid #f0f0f0;
border-radius: 8px;
margin-bottom: 12px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
&:hover {
border-color: #1677ff;
background: #f8f9ff;
}
&.unread {
border-left: 4px solid #1677ff;
background: #f0f8ff;
}
.message-icon {
width: 40px;
height: 40px;
border-radius: 50%;
background: #1677ff;
color: white;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
i {
font-size: 16px;
}
}
.message-content {
flex: 1;
.message-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 8px;
.message-title {
font-size: 16px;
color: #333;
margin: 0;
font-weight: 500;
}
.message-time {
font-size: 12px;
color: #999;
white-space: nowrap;
margin-left: 12px;
}
}
.message-text {
font-size: 14px;
color: #666;
margin: 0;
line-height: 1.5;
}
}
.unread-dot {
width: 8px;
height: 8px;
background: #1677ff;
border-radius: 50%;
position: absolute;
top: 16px;
right: 16px;
}
}
}
.empty-state {
text-align: center;
padding: 60px 20px;
color: #999;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
i {
font-size: 48px;
margin-bottom: 16px;
display: block;
}
p {
font-size: 14px;
margin: 0;
}
}
</style>