| | |
| | | </div> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item command="info"> |
| | | <span>基本信息</span> |
| | | </el-dropdown-item> |
| | | <!-- <el-dropdown-item command="info">--> |
| | | <!-- <span>基本信息</span>--> |
| | | <!-- </el-dropdown-item>--> |
| | | <el-dropdown-item command="password"> |
| | | <span>修改密码</span> |
| | | </el-dropdown-item> |
| | |
| | | v-for="system in systems" |
| | | :key="system.id" |
| | | class="system-card" |
| | | @mouseenter="handleCardEnter($event, system.id)" |
| | | @mousemove="handleCardMove($event, system.id)" |
| | | @mouseleave="handleCardLeave(system.id)" |
| | | @click="enterSystem(system.id)" |
| | | :style="getCardStyle(system.id)" |
| | | > |
| | | <div class="card-content"> |
| | | <div class="system-icon"> |
| | | <img :src="system.icon"/> |
| | | </div> |
| | | <h3>{{ system.name }}</h3> |
| | | <p>{{ system.description }}</p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | const userInfo = ref(); |
| | | const userName = ref('') |
| | | const userTypeName = ref('') |
| | | const cardStates = ref({}) |
| | | // 组件挂载时获取用户信息和系统列表 |
| | | onMounted(() => { |
| | | if(getToken()){ |
| | |
| | | |
| | | const userStore = useUserStore() |
| | | userStore.roles = [] |
| | | systems.value.forEach(system => { |
| | | cardStates.value[system.id] = { |
| | | mouseX: 0, |
| | | mouseY: 0, |
| | | width: 0, |
| | | height: 0, |
| | | hover: false |
| | | } |
| | | }) |
| | | }) |
| | | |
| | | |
| | | // 鼠标进入卡片 |
| | | const handleCardEnter = (event, id) => { |
| | | const card = event.currentTarget |
| | | cardStates.value[id] = { |
| | | ...cardStates.value[id], |
| | | width: card.offsetWidth, |
| | | height: card.offsetHeight, |
| | | hover: true |
| | | } |
| | | } |
| | | |
| | | // 鼠标移动 |
| | | const handleCardMove = (event, id) => { |
| | | if (!cardStates.value[id]?.hover) return |
| | | |
| | | const card = event.currentTarget |
| | | const rect = card.getBoundingClientRect() |
| | | |
| | | cardStates.value[id].mouseX = event.clientX - rect.left - cardStates.value[id].width / 2 |
| | | cardStates.value[id].mouseY = event.clientY - rect.top - cardStates.value[id].height / 2 |
| | | } |
| | | |
| | | // 鼠标离开 |
| | | const handleCardLeave = (id) => { |
| | | cardStates.value[id].hover = false; |
| | | // 立即开始归位动画,不使用setTimeout延迟 |
| | | cardStates.value[id].mouseX = 0; |
| | | cardStates.value[id].mouseY = 0; |
| | | } |
| | | |
| | | // 获取卡片样式 |
| | | const getCardStyle = (id) => { |
| | | const state = cardStates.value[id] || {} |
| | | const mousePX = state.mouseX / (state.width || 1) |
| | | const mousePY = state.mouseY / (state.height || 1) |
| | | |
| | | const rX = mousePX * 18 // 减小旋转角度,使效果更柔和 |
| | | const rY = mousePY * -18 |
| | | |
| | | const tX = mousePX * -20 |
| | | const tY = mousePY * -20 |
| | | |
| | | return { |
| | | transform: `rotateY(${rX}deg) rotateX(${rY}deg)`, |
| | | '--bg-transform': `translateX(${tX}px) translateY(${tY}px)` |
| | | } |
| | | } |
| | | |
| | | |
| | | // 系统列表 |
| | | const systems = ref([ |
| | | { |
| | |
| | | margin: 0; |
| | | color: #333; |
| | | text-align: center; |
| | | font-size: 28px; |
| | | letter-spacing: 2px; |
| | | } |
| | | |
| | | .avatar-container { |
| | |
| | | justify-content: center; |
| | | |
| | | .avatar-wrapper { |
| | | margin-top: 15px; |
| | | position: relative; |
| | | |
| | | .user-avatar { |
| | |
| | | |
| | | .systems-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); |
| | | gap: 20px; |
| | | grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); |
| | | gap: 30px; |
| | | max-width: 1500px; |
| | | margin: 0 auto; |
| | | perspective: 1000px; |
| | | } |
| | | |
| | | .system-card { |
| | | display: flex; |
| | | height: 200px; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 20px; |
| | | position: relative; |
| | | height: 280px; |
| | | background-color: #ffffff; |
| | | border-radius: 8px; |
| | | transition: transform 0.3s, box-shadow 0.3s; |
| | | border-radius: 4px; |
| | | transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), |
| | | box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1); |
| | | transform-style: preserve-3d; |
| | | cursor: pointer; |
| | | overflow: hidden; |
| | | |
| | | &:hover{ |
| | | border-radius: 16px; |
| | | } |
| | | |
| | | &::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 8px; |
| | | left: 8px; |
| | | right: 8px; |
| | | bottom: 8px; |
| | | border-radius: 4px; /* 比卡片小1px */ |
| | | border: 1px solid transparent; |
| | | transition: border-color 0.3s ease; |
| | | pointer-events: none; /* 确保不影响鼠标事件 */ |
| | | z-index: 3; /* 确保在内容之上 */ |
| | | } |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | border-radius: 4px; |
| | | background: #fff; |
| | | transform: var(--bg-transform, translateX(0) translateY(0)); |
| | | transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1); |
| | | z-index: 1; |
| | | } |
| | | &:hover::after { |
| | | border-color: rgba(37,99,235,1); /* 使用蓝色描边 */ |
| | | border-radius: 12px; |
| | | box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5); /* 可选:添加内发光效果 */ |
| | | } |
| | | &:hover::before { |
| | | border-radius: 16px; |
| | | background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(0,0,0,0.05) 100%); |
| | | } |
| | | } |
| | | |
| | | .system-card:hover { |
| | | transform: translateY(-5px); |
| | | box-shadow: 0 6px 12px rgba(100, 100, 100, 0.1); |
| | | //transform: translateY(-5px); |
| | | box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.5) inset; |
| | | } |
| | | .card-content { |
| | | position: relative; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 25px; |
| | | z-index: 2; |
| | | transform-style: preserve-3d; |
| | | } |
| | | |
| | | .system-icon img { |
| | | width: 60px; |
| | | height: 60px; |
| | | margin-bottom: 15px; |
| | | width: 80px; |
| | | height: 80px; |
| | | margin-bottom: 30px; |
| | | transition: transform 0.5s; |
| | | } |
| | | |
| | | .system-card:hover .system-icon img { |
| | | transform: scale(1.3); |
| | | } |
| | | |
| | | .system-card h3 { |
| | | margin: 0 0 10px; |
| | | margin: 0 0 12px; |
| | | color: #333; |
| | | font-size: 24px; |
| | | text-align: center; |
| | | transition: transform 0.3s; |
| | | } |
| | | |
| | | .system-card p { |
| | | margin: 0; |
| | | color: #666; |
| | | font-size: 14px; |
| | | color: #999; |
| | | font-size: 15px; |
| | | text-align: center; |
| | | transition: transform 0.3s; |
| | | } |
| | | |
| | | .system-card:hover h3, |
| | | .system-card:hover p { |
| | | transform: translateZ(20px); |
| | | } |
| | | </style> |