You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
763 lines
21 KiB
763 lines
21 KiB
<script setup>
|
|
import {computed, onMounted, ref} from 'vue'
|
|
import {useRoute, useRouter} from 'vue-router'
|
|
import {ElMessage} from 'element-plus'
|
|
import ChangePassword from '@/components/dialogs/changePassword.vue'
|
|
import {useAdminStore} from '@/store'
|
|
import {storeToRefs} from 'pinia'
|
|
import {filterMenu, getRoutePath} from "@/utils/menuUtils.js";
|
|
import API from '@/util/http.js'
|
|
|
|
import bell from '@/assets/SvgIcons/bell.svg'
|
|
import noMessage from '@/assets/images/no-message.svg'
|
|
import goTop from '@/assets/SvgIcons/go-top.svg'
|
|
|
|
import {getOrderPage} from '@/utils/goToCheck.js'
|
|
import {groupMessages} from "@/utils/getMessage.js"
|
|
|
|
import {useMessageStore} from '@/store/index.js'
|
|
|
|
// ------------------ ICONS ------------------
|
|
const icons = import.meta.glob('@/assets/SvgIcons/*.svg', {eager: true})
|
|
|
|
const menuNameMap = {
|
|
'工作台': 'workbench',
|
|
'金币管理': 'gold-management',
|
|
'现金管理': 'cash-management',
|
|
'活动管理': 'activity-management',
|
|
'频道管理': 'channel-management',
|
|
'权限管理': 'permission-management',
|
|
}
|
|
|
|
const getIconPath = (menuName) => {
|
|
const englishName = menuNameMap[menuName] || menuName;
|
|
|
|
const possibleKeys = [
|
|
`@/assets/SvgIcons/${englishName}.svg`,
|
|
`./SvgIcons/${englishName}.svg`,
|
|
`/src/assets/SvgIcons/${englishName}.svg`
|
|
]
|
|
|
|
for (const key of possibleKeys) {
|
|
if (icons[key]) {
|
|
const iconModule = icons[key]
|
|
return iconModule.default || iconModule
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------ 刷新数据 ------------------
|
|
const refreshData = async () => {
|
|
try {
|
|
ElMessage({message: '数据刷新中,请稍候...', type: 'info'});
|
|
const response = await API({url: '/Mysql', method: 'POST', data: {}});
|
|
|
|
if (response && response.code === 200) {
|
|
const currentRoute = route.fullPath;
|
|
router.replace('/blank');
|
|
setTimeout(() => router.replace(currentRoute), 10);
|
|
ElMessage.success('数据刷新成功');
|
|
} else {
|
|
ElMessage.error('数据刷新失败:' + (response?.msg || '未知错误'));
|
|
}
|
|
} catch (error) {
|
|
console.error(error)
|
|
ElMessage.error('数据刷新异常,请重试');
|
|
}
|
|
}
|
|
|
|
// ------------------ 菜单逻辑 ------------------
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
|
|
const adminStore = useAdminStore()
|
|
const {adminData, menuTree, flag} = storeToRefs(adminStore)
|
|
|
|
const menuList = ref(filterMenu(menuTree.value))
|
|
|
|
function findBestMatch(menuList, path) {
|
|
let bestMatch = ''
|
|
|
|
function traverse(menus) {
|
|
for (const item of menus) {
|
|
const itemPath = getRoutePath(item)
|
|
if (path.startsWith(itemPath) && itemPath.length > bestMatch.length) {
|
|
bestMatch = itemPath
|
|
}
|
|
if (item.children?.length) traverse(item.children)
|
|
}
|
|
}
|
|
|
|
traverse(menuList)
|
|
return bestMatch || path
|
|
}
|
|
|
|
const activeMenu = computed(() => findBestMatch(menuList.value, route.path))
|
|
|
|
// ------------------ 用户信息 / 密码修改 ------------------
|
|
const messageVisible = ref(false)
|
|
const openMessage = () => (messageVisible.value = true)
|
|
const closeMessage = () => (messageVisible.value = false)
|
|
|
|
const showPasswordDialog = ref(false)
|
|
const pwdRef = ref()
|
|
|
|
const openChangePassword = () => (showPasswordDialog.value = true)
|
|
const onPwdDialogClosed = () => pwdRef.value?.resetFields()
|
|
|
|
// ------------------ 退出登录 ------------------
|
|
function logout() {
|
|
const machineId = localStorage.getItem('machineId')
|
|
localStorage.removeItem('token')
|
|
adminStore.clearState()
|
|
router.push('/login?machineId=' + machineId)
|
|
ElMessage.success('退出成功')
|
|
}
|
|
|
|
// ------------------ 员工数据开关 ------------------
|
|
const toggleFlag = () => {
|
|
const newFlag = flag.value === 1 ? 0 : 1
|
|
adminStore.setFlag(newFlag)
|
|
ElMessage.success(newFlag === 1 ? '员工数据已隐藏' : '员工数据已显示')
|
|
}
|
|
|
|
// ------------------ 消息中心(完全修复版) ------------------
|
|
const messageStore = useMessageStore()
|
|
const {messages} = storeToRefs(messageStore)
|
|
|
|
// 获取消息
|
|
const getMessage = async () => {
|
|
try {
|
|
const res = await API({
|
|
url: '/getMessage',
|
|
method: 'POST',
|
|
data: {}
|
|
});
|
|
|
|
if (res?.data) {
|
|
const cleanList = res.data.filter(i => i.flag !== 1)
|
|
messageStore.setMessages(cleanList)
|
|
}
|
|
} catch (e) {
|
|
console.error("getMessage error:", e)
|
|
}
|
|
}
|
|
|
|
// 点击铃铛 → 打开弹窗并刷新
|
|
const showMessageDialog = ref(false)
|
|
const openMessageDialog = async () => {
|
|
showMessageDialog.value = true
|
|
await getMessage() // 等待消息更新
|
|
}
|
|
|
|
// 关闭消息窗口
|
|
const closeMessageDialog = () => showMessageDialog.value = false
|
|
|
|
// 小红点(完全响应式)
|
|
const messageDot = computed(() => messages.value.length > 0)
|
|
|
|
// 消息数量(完全响应式)
|
|
const messageNum = computed(() => messages.value.length)
|
|
|
|
// 按日期分组(computed)
|
|
const messageList = computed(() => groupMessages(messages.value))
|
|
|
|
// 按日期生成最终结构(computed)
|
|
const groupedMessages = computed(() => {
|
|
const result = {}
|
|
messageList.value.forEach(item => {
|
|
if (!result[item.group]) result[item.group] = []
|
|
result[item.group].push(item)
|
|
})
|
|
return result
|
|
})
|
|
|
|
// 显示全部 or 显示前两条
|
|
const showAll = ref(false)
|
|
|
|
const displayMessages = computed(() => {
|
|
if (showAll.value) return groupedMessages.value
|
|
|
|
let count = 0
|
|
const limited = {}
|
|
const groupOrder = ['今天', '昨天', '更早']
|
|
|
|
for (const g of groupOrder) {
|
|
const group = groupedMessages.value[g]
|
|
if (!group) continue
|
|
|
|
limited[g] = []
|
|
for (const item of group) {
|
|
if (count < 2) {
|
|
limited[g].push(item)
|
|
count++
|
|
}
|
|
}
|
|
if (limited[g].length === 0) delete limited[g]
|
|
if (count >= 2) break
|
|
}
|
|
return limited
|
|
})
|
|
|
|
const toggleShowAll = () => showAll.value = !showAll.value
|
|
|
|
// 返回顶部
|
|
const scrollContainer = ref(null)
|
|
const scrollToTop = () => scrollContainer.value?.scrollTo({top: 0, behavior: 'smooth'})
|
|
|
|
// 点击消息 → 已读 + 跳转
|
|
const handleMessageClick = async (item) => {
|
|
const res = await API({
|
|
url: '/getMessage/update',
|
|
method: 'POST',
|
|
data: {id: item.id}
|
|
});
|
|
|
|
if (res.code === 200) {
|
|
closeMessageDialog()
|
|
await router.push(getOrderPage(item.status))
|
|
await getMessage()
|
|
ElMessage.success('跳转成功')
|
|
} else {
|
|
ElMessage.error('跳转失败')
|
|
}
|
|
}
|
|
|
|
onMounted(() => getMessage())
|
|
</script>
|
|
<template>
|
|
<div class="main-container">
|
|
<!-- 背景毛玻璃层(作为内容容器) -->
|
|
<div class="background-glass">
|
|
<!-- 侧边栏 -->
|
|
<div class="sidebar-container">
|
|
<el-aside class="sidebar-layout">
|
|
<div class="logo">
|
|
<img src="../assets/logo.png" alt="logo" style="width: 9vh; height: 9vh"/>
|
|
</div>
|
|
|
|
<div class="menu-scroll-container">
|
|
<el-menu :router="true" :default-active="activeMenu" style="min-height: 80vh;border:none;">
|
|
<!-- 递归渲染菜单层级 -->
|
|
<template v-for="menu in menuList" :key="menu.id">
|
|
<!-- 有子菜单的父级菜单(menuType=2 且存在children) -->
|
|
<el-sub-menu v-if="menu.children && menu.children.length > 0" :index="menu.id.toString()">
|
|
<template #title>
|
|
<img
|
|
:src="getIconPath(menu.menuName)"
|
|
:alt="`${menu.menuName}图标`"
|
|
style="width: 4vh; height: 4vh; margin-right: 4px;"
|
|
>
|
|
|
|
<span>{{ menu.menuName }}</span>
|
|
</template>
|
|
<!-- 子菜单 -->
|
|
<template v-for="child in menu.children" :key="child.id">
|
|
<!-- 子菜单为叶子节点(无children) -->
|
|
<el-menu-item v-if="!child.children || child.children.length === 0" :index="getRoutePath(child)">
|
|
<el-icon style="margin-right: 4px;">
|
|
<Folder/>
|
|
</el-icon>
|
|
<span>{{ child.menuName }}</span>
|
|
</el-menu-item>
|
|
|
|
<!-- 子菜单有下级 -->
|
|
<el-sub-menu v-else :index="child.id.toString()">
|
|
<template #title>
|
|
<el-icon style="margin-right: 4px;">
|
|
<Folder/>
|
|
</el-icon>
|
|
<span>{{ child.menuName }}</span>
|
|
</template>
|
|
<!-- 递归 下一级-->
|
|
<template v-for="grandChild in child.children" :key="grandChild.id">
|
|
<el-menu-item :index="getRoutePath(grandChild)">
|
|
<el-icon style="margin-right: 4px;">
|
|
<Folder/>
|
|
</el-icon>
|
|
<span>{{ grandChild.menuName }}</span>
|
|
</el-menu-item>
|
|
</template>
|
|
</el-sub-menu>
|
|
</template>
|
|
</el-sub-menu>
|
|
|
|
<!-- 无子菜单的一级菜单 -->
|
|
<el-menu-item v-else :index="getRoutePath(menu)">
|
|
<img
|
|
:src="getIconPath(menu.menuName)"
|
|
:alt="`${menu.menuName}图标`"
|
|
style="width: 4vh; height: 4vh; margin-right: 4px;"
|
|
>
|
|
<span>{{ menu.menuName }}</span>
|
|
</el-menu-item>
|
|
</template>
|
|
</el-menu>
|
|
</div>
|
|
|
|
<div style="display: flex">
|
|
<!-- 底部固定的设置中心 -->
|
|
<div class="settings-container">
|
|
<el-dropdown placement="top-start">
|
|
<span class="el-dropdown-link">
|
|
<!-- 暂时使用静态路径,确保设置图标正常显示 -->
|
|
<img src="@/assets/SvgIcons/setting.svg" alt="设置" style="width: 4vh; height: 4vh"/>
|
|
<span>设置中心</span>
|
|
<el-icon class="arrow-icon">
|
|
<ArrowUp/>
|
|
</el-icon>
|
|
</span>
|
|
<template #dropdown>
|
|
<el-dropdown-menu>
|
|
<!-- <el-dropdown-item @click="refreshData()">数据刷新</el-dropdown-item>-->
|
|
<!-- 员工数据开关 -->
|
|
<el-dropdown-item @click="toggleFlag()">
|
|
{{ flag === 1 ? '显示员工数据' : '隐藏员工数据' }}
|
|
</el-dropdown-item>
|
|
<el-dropdown-item @click="message()">查看个人信息</el-dropdown-item>
|
|
<el-dropdown-item @click="openChangePassword">修改密码</el-dropdown-item>
|
|
<el-dropdown-item @click="logout">退出登录</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</template>
|
|
</el-dropdown>
|
|
</div>
|
|
<!-- 消息提示 这里的 小红点不用el-badge 他在切换状态会抽一下 应该是dom问题 -->
|
|
<div class="message-container">
|
|
<div style="position: relative;">
|
|
<el-image :src="bell" style="width: 28px; height: 28px;" @click="openMessageDialog"></el-image>
|
|
<span v-show="messageDot" class="dot"></span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-aside>
|
|
</div>
|
|
|
|
<!-- 右侧内容区域 -->
|
|
<div class="content-container">
|
|
<!-- 头部
|
|
<el-header class="header">
|
|
|
|
</el-header> -->
|
|
|
|
<!-- 主内容区域 -->
|
|
<div class="main-area">
|
|
<el-main>
|
|
<router-view></router-view>
|
|
</el-main>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 查看个人信息 -->
|
|
<el-dialog v-model="messageVisible" title="查看个人信息" width="500px">
|
|
<el-form :model="adminData">
|
|
<el-form-item label="用户姓名" label-width="100px" label-position="left">
|
|
<span class="message-font">{{ adminData.adminName }}</span>
|
|
</el-form-item>
|
|
<el-form-item label="精网号" label-width="100px" label-position="left">
|
|
<span class="message-font">{{ adminData.account }}</span>
|
|
</el-form-item>
|
|
<el-form-item label="地区" label-width="100px" label-position="left">
|
|
<span class="message-font">{{ adminData.markets }}</span>
|
|
</el-form-item>
|
|
<el-form-item label="注册时间" label-width="100px" label-position="left">
|
|
<span class="message-font">{{ adminData.createTime }}</span>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<div>
|
|
<el-button text @click="closeMessage()">关闭</el-button>
|
|
</div>
|
|
</template>
|
|
</el-dialog>
|
|
|
|
<!-- 自定义密码修改弹窗组件 -->
|
|
<el-dialog v-model="showPasswordDialog" :center="true" width="470px" @closed="onPwdDialogClosed">
|
|
<ChangePassword ref="pwdRef" @confirm="showPasswordDialog = false"/>
|
|
</el-dialog>
|
|
|
|
<!--消息推送的弹窗-->
|
|
<el-dialog style="background: #F3FAFE" v-model="showMessageDialog" title="" width="500px">
|
|
<div class="message-title">
|
|
<el-divider
|
|
class="divider"
|
|
direction="vertical"
|
|
></el-divider>
|
|
消息中心 ({{ messageNum }})
|
|
</div>
|
|
<!-- todo 这是为了样式显示 一定要改逻辑-->
|
|
<div v-if="messageNum === 0">
|
|
<div class="no-message">
|
|
<el-image :src="noMessage"></el-image>
|
|
<p class="no-message-text">暂无未办消息,快去处理工作吧~</p>
|
|
</div>
|
|
</div>
|
|
<div v-else
|
|
ref="scrollContainer"
|
|
style="max-height: 60vh; overflow-y: auto;">
|
|
<!-- 按时间分组的消息列表 -->
|
|
<div
|
|
v-for="(group, time) in displayMessages"
|
|
:key="time"
|
|
style="margin-bottom: 16px;"
|
|
>
|
|
<div class="time-header">
|
|
{{ time }} <span class="little-dot"></span>
|
|
<el-divider
|
|
style="height: 2px; align-self: stretch;flex: 1;background: #CEE5FE; border: none;"
|
|
></el-divider>
|
|
</div>
|
|
<div
|
|
v-for="item in group"
|
|
:key="item.id"
|
|
class="message-item"
|
|
>
|
|
<div style="display: flex; margin-bottom: 10px">
|
|
<span class="red-dot"></span>
|
|
<span class="message-card-title">{{ item.title }}</span>
|
|
<div
|
|
class="message-time"
|
|
:style="{ color: item.czTime.includes('分钟') ? 'red' : '' }"
|
|
>
|
|
{{ item.czTime }}
|
|
</div>
|
|
</div>
|
|
|
|
<p class="message-desc">{{ item.desc }}</p>
|
|
<el-button
|
|
type="primary"
|
|
style="margin: 0 auto; display: block;"
|
|
@click="handleMessageClick(item)"
|
|
>
|
|
前往查看
|
|
</el-button>
|
|
</div>
|
|
<el-divider
|
|
style="height: 1px; align-self: stretch;flex: 1;background: #CEE5FE; border: none;"
|
|
></el-divider>
|
|
</div>
|
|
|
|
<!-- 控制按钮 -->
|
|
<div>
|
|
<el-button
|
|
type="text"
|
|
v-if="messageNum > 2"
|
|
class="view-all"
|
|
@click="toggleShowAll"
|
|
>
|
|
{{ showAll ? '收起' : '查看全部' }}
|
|
</el-button>
|
|
|
|
<div v-if="showAll" @click="scrollToTop" class="go-top">
|
|
<el-image
|
|
:src="goTop"
|
|
style="width: 20px; height: 20px;"
|
|
fit="contain"
|
|
/>
|
|
<span>返回顶部</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</el-dialog>
|
|
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
/* 主容器,设置背景图并居中 */
|
|
.main-container {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-image: url('@/assets/backgroundBlue.png');
|
|
background-size: cover;
|
|
background-position: center center;
|
|
background-repeat: no-repeat;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* 背景毛玻璃层(作为内容容器) */
|
|
.background-glass {
|
|
position: absolute;
|
|
top: 1vh;
|
|
left: 1vh;
|
|
right: 1vh;
|
|
bottom: 1vh;
|
|
background-image: url('@/assets/blue-background.png');
|
|
background-size: cover;
|
|
z-index: 1;
|
|
display: flex;
|
|
flex-direction: row;
|
|
padding: 10px;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
/* 侧边栏容器 */
|
|
.sidebar-container {
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
.logo {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 12vh;
|
|
|
|
}
|
|
|
|
/* 中间可滚动菜单容器 */
|
|
.menu-scroll-container {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 10px 0;
|
|
}
|
|
|
|
/* 底部设置中心样式 */
|
|
.settings-container {
|
|
padding: 10px 0 10px 20px; /* 上,右, 下,左 */
|
|
display: flex;
|
|
align-items: center; /* 垂直居中 */
|
|
}
|
|
|
|
/* 调整下拉菜单的样式,确保它向上弹出 */
|
|
|
|
.el-dropdown-link:focus {
|
|
/* 移除底部的异常效果 */
|
|
outline: none;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.el-dropdown-link {
|
|
display: flex;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
gap: 10px; /* 图标和文字左右间距 */
|
|
}
|
|
|
|
.sidebar-layout {
|
|
width: 15vw;
|
|
height: 100%;
|
|
background: #E7F4FD; /* 浅蓝色背景 */
|
|
/* backdrop-filter: blur(5px); 毛玻璃效果 --消耗性能 */
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); /* 添加阴影增强层次感 */
|
|
border-radius: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: relative;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
/* 内容区域容器 */
|
|
.content-container {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
margin-left: 5px;
|
|
gap: 5px;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
|
|
/* 主内容区域容器 */
|
|
.main-area {
|
|
flex: 1;
|
|
background: #E7F4FD;
|
|
/* 半透明浅色背景 */
|
|
/* backdrop-filter: blur(5px); */
|
|
/* 毛玻璃效果 */
|
|
border-radius: 12px;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
|
/* 添加阴影增强层次感 */
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* 主内容区域样式 */
|
|
.el-main {
|
|
height: 100%;
|
|
padding: 1px 8px 10px 8px;
|
|
background: transparent;
|
|
overflow-y: auto;
|
|
/* 应用自定义滚动条 */
|
|
}
|
|
|
|
|
|
/* 确保el-menu撑满容器 */
|
|
.sidebar-layout .el-menu {
|
|
width: 100%;
|
|
}
|
|
|
|
/* 侧边栏菜单样式 适配浅色背景 */
|
|
.el-menu {
|
|
background: transparent !important;
|
|
}
|
|
|
|
|
|
/* 工作台,金币管理,现金管理 */
|
|
::v-deep(.el-sub-menu__title:hover),
|
|
::v-deep(.el-menu-item:hover) {
|
|
background: #E5EBFE;
|
|
}
|
|
|
|
/* 子菜单展开时和背景同色 */
|
|
::v-deep(.el-sub-menu__title),
|
|
::v-deep(.el-menu-item) {
|
|
background: #E7F4FD;
|
|
}
|
|
|
|
|
|
.message-font {
|
|
/* 个人信息字体样式 */
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
|
|
/* 确保全局el-container适应容器 */
|
|
:deep(.el-container) {
|
|
/* vue3的深度选择器,用于覆盖element-plus的默认样式 */
|
|
min-height: 100%;
|
|
width: 100%;
|
|
background: transparent;
|
|
}
|
|
|
|
|
|
/* 为侧边栏和主内容区域添加滚动条样式 */
|
|
.menu-scroll-container,
|
|
.el-main {
|
|
scrollbar-width: thin;
|
|
/* Firefox */
|
|
scrollbar-color: rgba(0, 0, 0, 0.3) rgba(255, 255, 255, 0.2);
|
|
/* Firefox滑块和轨道颜色 */
|
|
}
|
|
|
|
/* 小红点 */
|
|
.dot {
|
|
position: absolute;
|
|
top: -2px;
|
|
right: -2px;
|
|
width: 8px;
|
|
height: 8px;
|
|
background: #F23C39;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
/* 消息中心整体容器 */
|
|
.message-container {
|
|
padding: 10px 50px 10px 50px; /* 上,右, 下,左 */
|
|
display: flex;
|
|
align-items: center; /* 垂直居中 */
|
|
}
|
|
|
|
/* 消息中心标题 */
|
|
.message-title {
|
|
display: flex;
|
|
font-size: 16px;
|
|
color: black;
|
|
|
|
.divider {
|
|
align-items: flex-start;
|
|
gap: 36px;
|
|
align-self: stretch;
|
|
height: 20px;
|
|
border-left: 3px solid #266EFF;
|
|
}
|
|
}
|
|
|
|
/* 无消息的样式 */
|
|
.no-message {
|
|
text-align: center;
|
|
position: relative;
|
|
|
|
.no-message-text {
|
|
position: absolute;
|
|
top: 60%;
|
|
left: 50%;
|
|
/* 水平垂直居中 */
|
|
transform: translate(-50%, -50%);
|
|
/* 文字样式 */
|
|
font-weight: bold;
|
|
margin: 0;
|
|
/* 可添加更多样式(如字体大小、阴影等) */
|
|
font-size: 14px;
|
|
}
|
|
}
|
|
|
|
|
|
/* 有消息的样式 */
|
|
.time-header {
|
|
font-size: 14px;
|
|
color: #666;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.message-item {
|
|
height: 100px;
|
|
padding: 10px 10px 10px 10px;
|
|
border-radius: 4px;
|
|
border: 1px solid #E5E5E5;
|
|
background: #FCFEFF;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.message-card-title {
|
|
font-weight: bold;
|
|
margin-right: 4px;
|
|
}
|
|
|
|
/* 圆点样式 */
|
|
.red-dot {
|
|
width: 6px;
|
|
height: 6px;
|
|
margin-right: 9px;
|
|
border-radius: 50%;
|
|
background-color: red;
|
|
}
|
|
|
|
.message-desc {
|
|
font-size: 13px;
|
|
color: #666;
|
|
margin: 4px 0 15px 15px;
|
|
}
|
|
|
|
.message-time {
|
|
margin-left: auto;
|
|
font-size: 13px;
|
|
color: #999;
|
|
}
|
|
|
|
.view-all {
|
|
display: block;
|
|
margin: 0 auto 16px;
|
|
}
|
|
|
|
.little-dot {
|
|
display: inline-block;
|
|
width: 8px; /* 圆点直径 */
|
|
height: 8px;
|
|
border-radius: 50%; /* 圆形 */
|
|
background-color: #CEE5FE;;
|
|
}
|
|
|
|
/* 返回最上*/
|
|
.go-top {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
cursor: pointer;
|
|
padding: 8px;
|
|
}
|
|
|
|
</style>
|