feat(路由): 添加用户和聊天页面路由

style(页脚): 更新版权信息和样式,添加链接和响应式设计

style(全局样式): 引入CSS变量,统一设计系统

refactor(主页面): 使用CSS变量优化样式,提升可维护性

style(购物车): 应用CSS变量,优化交互效果和动画

feat(头部导航): 增强用户信息展示和搜索类型切换动画

feat(聊天页面): 新增聊天功能界面,支持用户列表和消息交互

feat(用户信息): 重构用户信息页面,添加订单状态和功能菜单
This commit is contained in:
qingfeng1121
2026-01-12 13:56:17 +08:00
parent 0c07d33bf9
commit c287650fbb
9 changed files with 3685 additions and 220 deletions

View File

@@ -7,6 +7,8 @@ import Search from '../Views/Search.vue'
import ProductDetail from '../Views/product/productdetil.vue'
import Cart from '../Views/Cart.vue'
import Order from '../Views/Order.vue'
import User from '../Views/User/User.vue'
import Chat from '../Views/Chat.vue'
@@ -41,6 +43,17 @@ const routes = [
name: 'order',
component: Order
},
{
path: '/user',
name: 'user',
component: User
},
{
path: '/chat',
name: 'chat',
component: Chat
},
]
const router = createRouter({

View File

@@ -1,13 +1,112 @@
/* 全局样式 */
body {
height: 100%;
padding: 0 20px;
padding: 0 var(--spacing-lg);
background-color: var(--bg-color);
font-family: var(--font-family);
font-size: var(--font-size-base);
color: var(--text-primary);
margin: 0;
}
a {
text-decoration: none;
color: #000;
font-size: 16px;
color: var(--text-primary);
font-size: var(--font-size-base);
font-weight: bold;
transition: all 0.3s ease-in-out;
transition: all var(--transition-normal);
}
a:hover {
color: var(--primary-color);
}
:root {
/* 主色调 */
--primary-color: #ff5000;
--primary-hover: #ff7a45;
--primary-active: #ff3a00;
--primary-light: rgba(255, 80, 0, 0.05);
--primary-light-rgb: 255, 80, 0;
/* 辅助色 */
--secondary-color: #1890ff;
--secondary-hover: #40a9ff;
--success-color: #52c41a;
--success-light: #f6ffed;
--warning-color: #faad14;
--warning-light: #fff7e6;
--error-color: #ff4d4f;
--error-light: #fff2f0;
/* 登录按钮渐变色 */
--login-gradient-start: #667eea;
--login-gradient-end: #764ba2;
/* 中性色 */
--bg-color: #f5f5f5;
--bg-light: #fafafa;
--bg-primary-light: #fff5f5;
--bg-primary-lighter: #fff0f0;
--bg-primary-lightest: #fff0e8;
--card-bg: #ffffff;
--text-primary: #333333;
--text-dark: #2d3436;
--text-secondary: #666666;
--text-tertiary: #999999;
--border-color: #e0e0e0;
--border-light: #e8e8e8;
/* 字体 */
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--font-size-xs: 12px;
--font-size-sm: 14px;
--font-size-base: 16px;
--font-size-lg: 18px;
--font-size-xl: 20px;
--font-size-2xl: 24px;
--font-size-3xl: 32px;
--font-size-4xl: 36px;
/* 间距 */
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
--spacing-xxl: 40px;
/* 圆角 */
--border-radius-sm: 4px;
--border-radius-md: 8px;
--border-radius-lg: 12px;
--border-radius-xl: 16px;
--border-radius-2xl: 24px;
--border-radius-3xl: 28px;
--border-radius-full: 50%;
/* 阴影 */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.12);
--shadow-xl: 0 6px 20px rgba(0, 0, 0, 0.15);
--shadow-2xl: 0 12px 32px rgba(0, 0, 0, 0.2);
/* 过渡 */
--transition-fast: 0.2s ease;
--transition-normal: 0.3s ease;
--transition-slow: 0.5s ease;
--transition-transform: 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
/* 搜索框相关 */
--search-height: 52px;
--search-radius: 28px;
/* 消息相关 */
--message-radius: 18px;
/* 输入框相关 */
--input-bg: #f9fafb;
--input-error: #ef4444;
--error-bg: #fee2e2;
--error-text: #dc2626;
}

View File

@@ -263,24 +263,24 @@ const removeItem = (id: number) => {
#cart {
width: 100%;
min-height: 100vh;
background: linear-gradient(135deg, #f5f5f5 0%, #fafafa 100%);
padding: 20px;
background: linear-gradient(135deg, var(--bg-color) 0%, var(--bg-light) 100%);
padding: var(--spacing-md);
}
.cart-container {
max-width: 1400px;
margin: 0 auto;
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
border-radius: 16px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
background: linear-gradient(135deg, var(--card-bg) 0%, var(--bg-light) 100%);
border-radius: var(--border-radius-xl);
box-shadow: var(--shadow-md);
overflow: hidden;
border: 1px solid #f0f0f0;
border: 1px solid var(--border-color);
}
.cart-header {
padding: 20px 40px;
border-bottom: 3px solid #f0f0f0;
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
padding: var(--spacing-md) var(--spacing-xxl);
border-bottom: 3px solid var(--border-color);
background: linear-gradient(135deg, var(--card-bg) 0%, var(--bg-light) 100%);
display: block;
align-items: center;
position: relative;
@@ -294,7 +294,7 @@ const removeItem = (id: number) => {
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 80, 0, 0.05), transparent);
background: linear-gradient(90deg, transparent, var(--primary-light), transparent);
transition: left 0.6s ease;
}
@@ -303,94 +303,94 @@ const removeItem = (id: number) => {
}
.cart-title {
font-size: 32px;
font-size: var(--font-size-3xl);
font-weight: 800;
color: #2d3436;
color: var(--text-dark);
margin: 0;
display: flex;
align-items: center;
gap: 15px;
gap: var(--spacing-md);
position: relative;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
transition: all var(--transition-transform);
}
.cart-title:hover {
color: #ff5000;
transform: translateX(8px);
text-shadow: 0 4px 8px rgba(255, 80, 0, 0.2);
color: var(--primary-color);
transform: translateX(var(--spacing-sm));
text-shadow: 0 4px 8px rgba(var(--primary-light-rgb), 0.2);
}
.cart-title i {
font-size: 36px;
color: #ff5000;
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
font-size: var(--font-size-4xl);
color: var(--primary-color);
transition: all var(--transition-transform);
}
.cart-title:hover i {
transform: rotate(10deg) scale(1.2);
filter: drop-shadow(0 2px 6px rgba(255, 80, 0, 0.3));
filter: drop-shadow(0 2px 6px rgba(var(--primary-light-rgb), 0.3));
}
.filter-buttons {
margin-top: 20px;
margin-top: var(--spacing-md);
display: flex;
gap: 20px;
gap: var(--spacing-md);
position: relative;
}
.filter-btn {
padding: 12px 36px;
border-radius: 28px;
font-size: 15px;
padding: var(--spacing-sm) var(--spacing-xxl);
border-radius: var(--border-radius-3xl);
font-size: var(--font-size-sm);
font-weight: 600;
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 2px solid #e0e0e0;
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: all var(--transition-transform);
border: 2px solid var(--border-color);
background: linear-gradient(135deg, var(--card-bg) 0%, var(--bg-light) 100%);
box-shadow: var(--shadow-md);
letter-spacing: 0.5px;
}
.filter-btn.active {
background: linear-gradient(135deg, #ff5000 0%, #ff6b00 100%);
border-color: #ff5000;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
border-color: var(--primary-color);
color: #ffffff;
box-shadow: 0 6px 20px rgba(255, 80, 0, 0.35);
box-shadow: 0 6px 20px rgba(var(--primary-light-rgb), 0.35);
transform: translateY(-2px);
}
.filter-btn:not(.active):hover {
border-color: #ff5000;
color: #ff5000;
background: linear-gradient(135deg, #fff5f5 0%, #fff0f0 100%);
box-shadow: 0 4px 16px rgba(255, 80, 0, 0.15);
border-color: var(--primary-color);
color: var(--primary-color);
background: linear-gradient(135deg, var(--bg-primary-light) 0%, var(--bg-primary-lighter) 100%);
box-shadow: 0 4px 16px rgba(var(--primary-light-rgb), 0.15);
transform: translateY(-2px);
}
.filter-btn:active {
transform: translateY(0);
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.2);
box-shadow: 0 2px 8px rgba(var(--primary-light-rgb), 0.2);
}
.cart-list {
padding: 20px 40px;
padding: var(--spacing-md) var(--spacing-xxl);
min-height: 400px;
}
.cart-item {
display: flex;
align-items: center;
padding: 15px;
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
border-radius: 24px;
margin-bottom: 30px;
border: 2px solid #f5f5f5;
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
padding: var(--spacing-md);
background: linear-gradient(135deg, var(--card-bg) 0%, var(--bg-light) 100%);
border-radius: var(--border-radius-2xl);
margin-bottom: var(--spacing-xl);
border: 2px solid var(--border-color);
transition: all var(--transition-transform);
box-shadow: var(--shadow-md);
position: relative;
overflow: hidden;
gap: 30px;
gap: var(--spacing-xl);
animation: float 6s ease-in-out infinite;
}
@@ -406,55 +406,55 @@ const removeItem = (id: number) => {
width: 26px;
height: 26px;
cursor: pointer;
accent-color: #ff5000;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
accent-color: var(--primary-color);
transition: all var(--transition-transform);
position: relative;
border-radius: 6px;
background-color: #ffffff;
border: 2px solid #e0e0e0;
border-radius: var(--border-radius-md);
background-color: var(--card-bg);
border: 2px solid var(--border-color);
}
.checkbox-input:hover {
transform: scale(1.2);
box-shadow: 0 0 0 10px rgba(255, 80, 0, 0.12);
border-color: #ff5000;
box-shadow: 0 0 0 10px rgba(var(--primary-light-rgb), 0.12);
border-color: var(--primary-color);
}
.checkbox-input:checked {
box-shadow: 0 0 0 8px rgba(255, 80, 0, 0.25);
border-color: #ff5000;
box-shadow: 0 0 0 8px rgba(var(--primary-light-rgb), 0.25);
border-color: var(--primary-color);
animation: checkbox-pulse 0.4s ease;
}
.checkbox-input:focus {
outline: none;
box-shadow: 0 0 0 6px rgba(255, 80, 0, 0.2);
border-color: #ff5000;
box-shadow: 0 0 0 6px rgba(var(--primary-light-rgb), 0.2);
border-color: var(--primary-color);
}
@keyframes checkbox-pulse {
0% {
box-shadow: 0 0 0 4px rgba(255, 80, 0, 0.2);
box-shadow: 0 0 0 4px rgba(var(--primary-light-rgb), 0.2);
}
50% {
box-shadow: 0 0 0 12px rgba(255, 80, 0, 0.1);
box-shadow: 0 0 0 12px rgba(var(--primary-light-rgb), 0.1);
}
100% {
box-shadow: 0 0 0 8px rgba(255, 80, 0, 0.25);
box-shadow: 0 0 0 8px rgba(var(--primary-light-rgb), 0.25);
}
}
.cart-item-img-container {
width: 150px;
height: 150px;
border-radius: 20px;
border-radius: var(--border-radius-xl);
overflow: hidden;
border: 3px solid #f0f0f0;
border: 3px solid var(--border-color);
flex-shrink: 0;
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
transition: all var(--transition-transform);
position: relative;
background: linear-gradient(135deg, #fafafa 0%, #ffffff 100%);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
background: linear-gradient(135deg, var(--bg-light) 0%, var(--card-bg) 100%);
box-shadow: var(--shadow-lg);
}
.cart-item-img-container::after {
@@ -464,10 +464,10 @@ const removeItem = (id: number) => {
left: 0;
right: 0;
bottom: 0;
border-radius: 20px;
border-radius: var(--border-radius-xl);
border: 3px solid transparent;
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
background: linear-gradient(135deg, rgba(255, 80, 0, 0.08) 0%, rgba(255, 80, 0, 0.03) 100%);
transition: all var(--transition-transform);
background: linear-gradient(135deg, rgba(var(--primary-light-rgb), 0.08) 0%, rgba(var(--primary-light-rgb), 0.03) 100%);
opacity: 0;
}
@@ -478,21 +478,21 @@ const removeItem = (id: number) => {
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255, 80, 0, 0.1), transparent);
background: linear-gradient(45deg, transparent, rgba(var(--primary-light-rgb), 0.1), transparent);
transform: rotate(45deg);
transition: all 0.6s ease;
transition: all var(--transition-slow);
opacity: 0;
}
.cart-item:hover .cart-item-img-container {
border-color: #ff5000;
border-color: var(--primary-color);
transform: scale(1.1) translateY(-4px);
box-shadow: 0 12px 32px rgba(255, 80, 0, 0.2);
box-shadow: 0 12px 32px rgba(var(--primary-light-rgb), 0.2);
}
.cart-item:hover .cart-item-img-container::after {
border-color: #ff5000;
box-shadow: 0 0 0 8px rgba(255, 80, 0, 0.2);
border-color: var(--primary-color);
box-shadow: 0 0 0 8px rgba(var(--primary-light-rgb), 0.2);
opacity: 1;
}
@@ -524,9 +524,9 @@ const removeItem = (id: number) => {
}
.cart-item-name {
font-size: 18px;
font-size: var(--font-size-lg);
font-weight: 700;
color: #333;
color: var(--text-primary);
margin: 0;
overflow: hidden;
/* 限制显示两行 */
@@ -535,15 +535,15 @@ const removeItem = (id: number) => {
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
line-height: 1.5;
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
transition: all var(--transition-transform);
position: relative;
letter-spacing: 0.5px;
}
.cart-item:hover .cart-item-name {
color: #ff5000;
transform: translateX(8px);
text-shadow: 0 2px 6px rgba(255, 80, 0, 0.2);
color: var(--primary-color);
transform: translateX(var(--spacing-sm));
text-shadow: 0 2px 6px rgba(var(--primary-light-rgb), 0.2);
}
.cart-item-name::after {

703
src/Views/Chat.vue Normal file
View File

@@ -0,0 +1,703 @@
<!-- 聊天界面 -->
<template>
<div>
<div id="chat">
<!-- 左右结构 左边聊天导航栏用户1 用户2 用户3 从上到下分布 一个用户一个li标签 右边聊天内容根据导航栏切换 -->
<div id="chat-nav">
<div class="nav-header">
<h2>消息</h2>
<!-- 搜索框 -->
<div class="search-container">
<input type="text" placeholder="搜索用户" v-model="searchTerm" class="search-input">
<i class="fas fa-search search-icon"></i>
</div>
</div>
<div class="user-list-container">
<ul class="user-list">
<li v-for="user in chatUsers" :key="user.id" :class="{ active: activeUserId === user.id }"
@click="selectUser(user.id)">
<div class="user-avatar">
<img :src="user.avatar" :alt="user.name">
</div>
<div class="user-info">
<div class="user-header">
<span class="user-name">{{ user.name }}</span>
<span class="message-time">{{ user.lastMessageTime }}</span>
</div>
<div class="user-last-message">
{{ user.lastMessage }}
</div>
</div>
<div v-if="user.unreadCount > 0" class="unread-badge">
{{ user.unreadCount }}
</div>
</li>
</ul>
</div>
</div>
<!-- 右边聊天内容 -->
<div id="chat-content">
<!-- 聊天头部 -->
<div v-if="activeUser" class="chat-header">
<div class="chat-user-info">
<div>
<h3>{{ activeUser.name }}</h3>
<p class="user-status">在线</p>
</div>
</div>
</div>
<!-- 聊天历史 -->
<div v-if="activeUser" class="chat-history">
<div v-for="(message, index) in messages" :key="index"
:class="{ 'chat-message': true, 'sent': message.sender === 'me', 'received': message.sender !== 'me' }">
<div v-if="message.sender !== 'me'" class="user-avatar small">
<img :src="activeUser.avatar" :alt="activeUser.name">
</div>
<div class="message-content">
<div class="message-text">{{ message.text }}</div>
<div class="message-time">{{ message.time }}</div>
</div>
</div>
</div>
<!-- 消息输入区 -->
<div v-if="activeUser" class="chat-input-area">
<div class="input-container">
<button class="input-btn">😊</button>
<button class="input-btn">📎</button>
<input type="text" v-model="newMessage" placeholder="输入消息..." class="message-input"
@keyup.enter="sendMessage">
<button class="input-btn">🎤</button>
</div>
<button class="send-btn" @click="sendMessage">发送</button>
</div>
<!-- 空状态 -->
<div v-else class="empty-state">
<img src="#" alt="选择聊天">
<h3>选择一个聊天</h3>
<p>开始与您的联系人聊天</p>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
// 搜索用户的关键词
const searchTerm = ref('')
// 聊天用户数据
const chatUsers = ref([
{
id: 1,
name: '用户1',
avatar: '?prompt=user%20avatar%20friendly%20smile&image_size=square',
lastMessage: '你好我想购买商品1',
lastMessageTime: '10:00',
unreadCount: 2
},
{
id: 2,
name: '用户2',
avatar: '?prompt=user%20avatar%20professional%20business&image_size=square',
lastMessage: '订单什么时候发货?',
lastMessageTime: '09:30',
unreadCount: 0
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
},
{
id: 3,
name: '用户3',
avatar: '?prompt=user%20avatar%20casual%20young&image_size=square',
lastMessage: '商品质量怎么样?',
lastMessageTime: '昨天',
unreadCount: 1
}
])
// 消息数据
const messages = ref([
{
sender: 'user1',
text: '你好我想购买商品1',
time: '10:00'
},
{
sender: 'me',
text: '您好,欢迎咨询,请问有什么可以帮助您的?',
time: '10:01'
},
{
sender: 'user1',
text: '商品1有货吗',
time: '10:02'
}
])
// 当前活跃用户ID
const activeUserId = ref(1)
// 新消息
const newMessage = ref('')
// 计算当前活跃用户
const activeUser = computed(() => {
return chatUsers.value.find(user => user.id === activeUserId.value)
})
// 选择用户
const selectUser = (userId: number) => {
activeUserId.value = userId
// 清除未读消息数
const user = chatUsers.value.find(user => user.id === userId)
if (user) {
user.unreadCount = 0
}
}
// 发送消息
const sendMessage = () => {
if (newMessage.value.trim()) {
messages.value.push({
sender: 'me',
text: newMessage.value,
time: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
})
// 更新最后一条消息
if (activeUser.value) {
activeUser.value.lastMessage = newMessage.value
activeUser.value.lastMessageTime = new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
}
// 清空输入框
newMessage.value = ''
}
}
</script>
<style scoped>
#chat {
background-color: var(--bg-color);
display: flex;
justify-content: center;
box-sizing: border-box;
border-radius: var(--border-radius-lg);
padding: var(--spacing-xl) 150px 0 150px;
}
/* 左侧聊天导航栏 */
#chat-nav {
width: 320px;
background-color: var(--bg-color);
display: flex;
flex-direction: column;
flex-shrink: 0;
border-radius: var(--border-radius-lg) 0 0 var(--border-radius-lg);
padding: var(--spacing-sm) 0 0 var(--spacing-sm);
border: 1px solid var(--border-color);
border-right: none;
}
.nav-header {
padding: var(--spacing-md);
align-items: center;
}
.nav-header h2 {
margin: 0;
font-size: var(--font-size-lg);
font-weight: 600;
color: var(--text-primary);
}
.search-container {
margin-top: var(--spacing-sm);
padding: var(--spacing-sm) var(--spacing-md);
display: flex;
align-items: center;
border-radius: var(--border-radius-xl);
border: 1px solid var(--border-color);
}
.search-input {
flex: 1;
border: none;
outline: none;
background: transparent;
font-size: var(--font-size-sm);
color: var(--text-primary);
}
.search-icon {
font-size: var(--font-size-base);
color: var(--text-tertiary);
margin-left: var(--spacing-sm);
}
.user-list-container {
background-color: var(--card-bg);
overflow-x: auto;
max-height: 50vh;
}
.new-chat-btn {
width: 32px;
height: 32px;
border-radius: var(--border-radius-full);
background-color: var(--primary-color);
color: #ffffff;
border: none;
font-size: var(--font-size-lg);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all var(--transition-normal);
}
.new-chat-btn:hover {
background-color: var(--primary-hover);
transform: scale(1.1);
}
#chat-nav .user-list-container ul {
list-style: none;
padding: 0;
margin: 0;
flex: 1;
overflow-y: auto;
}
#chat-nav .user-list-container li {
display: flex;
align-items: center;
padding: var(--spacing-md) var(--spacing-md);
cursor: pointer;
transition: all var(--transition-normal);
}
#chat-nav .user-list-container li:hover {
background-color: var(--bg-color);
border-radius: var(--border-radius-sm);
}
#chat-nav .user-list-container li.active {
background-color: var(--bg-primary-lightest);
border-radius: var(--border-radius-sm);
}
.user-avatar {
width: 50px;
height: 50px;
border-radius: var(--border-radius-full);
overflow: hidden;
margin-right: var(--spacing-md);
flex-shrink: 0;
border-radius: var(--border-radius-lg);
}
.user-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.user-avatar.small {
width: 36px;
height: 36px;
margin-right: var(--spacing-sm);
}
.user-info {
flex: 1;
min-width: 0;
}
.user-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--spacing-xs);
}
.user-name {
font-weight: 600;
color: var(--text-primary);
font-size: var(--font-size-sm);
}
.message-time {
font-size: var(--font-size-xs);
color: var(--text-tertiary);
}
.user-last-message {
font-size: var(--font-size-xs);
color: var(--text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.unread-badge {
background-color: var(--primary-color);
color: #ffffff;
font-size: var(--font-size-xs);
font-weight: 600;
padding: 2px 8px;
border-radius: var(--border-radius-xl);
min-width: 20px;
text-align: center;
margin-left: var(--spacing-sm);
}
/* 右侧聊天内容 */
#chat-content {
flex: 1;
display: flex;
flex-direction: column;
background-color: var(--bg-color);
border-radius: 0 var(--border-radius-lg) var(--border-radius-lg) 0;
border: 1px solid var(--border-color);
border-left: none;
}
/* 聊天头部 */
.chat-header {
background-color: var(--bg-color);
padding: var(--spacing-md) var(--spacing-md);
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 0 var(--border-radius-lg) 0 0;
}
.chat-user-info {
display: flex;
align-items: center;
width: 100%;
padding: 10px;
border-bottom: 1px solid #e0e0e0;
}
.chat-user-info h3 {
margin: 0 0 2px;
font-size: 16px;
font-weight: 600;
color: #333333;
}
.user-status {
font-size: 12px;
color: #4caf50;
margin: 0;
}
.chat-actions {
display: flex;
gap: 10px;
}
.action-btn {
width: 36px;
height: 36px;
border-radius: 50%;
background-color: #f0f0f0;
border: none;
cursor: pointer;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.action-btn:hover {
background-color: #e0e0e0;
}
/* 聊天历史 */
.chat-history {
flex: 1;
padding: 20px;
overflow-y: auto;
background-color: #f5f5f5;
background-image: url('?prompt=chat%20background%20pattern%20subtle%20light&image_size=landscape_16_9');
background-size: cover;
background-position: center;
}
.chat-message {
display: flex;
margin-bottom: 15px;
align-items: flex-end;
}
.chat-message.sent {
flex-direction: row-reverse;
}
.chat-message.sent .user-avatar {
margin-right: 0;
margin-left: 10px;
}
.message-content {
max-width: 70%;
display: flex;
flex-direction: column;
}
.chat-message.sent .message-content {
align-items: flex-end;
}
.message-text {
padding: 10px 15px;
border-radius: 18px;
margin-bottom: 4px;
line-height: 1.4;
}
.chat-message.received .message-text {
background-color: #ffffff;
border-bottom-left-radius: 4px;
}
.chat-message.sent .message-text {
background-color: #ff5000;
color: #ffffff;
border-bottom-right-radius: 4px;
}
.message-time {
font-size: 11px;
color: #999999;
}
/* 消息输入区 */
.chat-input-area {
background-color: #f5f5f5;
padding: 15px 20px;
border-top: 1px solid #e0e0e0;
border-radius: 0 0 10px 0;
display: flex;
align-items: center;
gap: 10px;
}
.input-container {
flex: 1;
display: flex;
align-items: center;
background-color: #f0f0f0;
border-radius: 24px;
padding: 8px 15px;
gap: 10px;
}
.input-btn {
background: none;
border: none;
font-size: 16px;
cursor: pointer;
padding: 4px;
}
.message-input {
flex: 1;
border: none;
background: none;
outline: none;
font-size: 14px;
color: #333333;
min-width: 0;
}
.message-input::placeholder {
color: #999999;
}
.send-btn {
padding: 8px 20px;
background-color: #ff5000;
color: #ffffff;
border: none;
border-radius: 20px;
cursor: pointer;
font-size: 14px;
font-weight: 600;
transition: all 0.3s ease;
}
.send-btn:hover {
background-color: #ff6a00;
}
/* 空状态 */
.empty-state {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
padding: 40px;
text-align: center;
}
.empty-state img {
width: 120px;
height: 120px;
margin-bottom: 20px;
opacity: 0.6;
}
.empty-state h3 {
margin: 0 0 10px;
font-size: 18px;
font-weight: 600;
color: #333333;
}
.empty-state p {
margin: 0;
font-size: 14px;
color: #999999;
}
/* 响应式设计 */
@media (max-width: 768px) {
#chat-nav {
width: 280px;
}
.chat-history {
padding: 15px;
}
.message-content {
max-width: 80%;
}
}
@media (max-width: 480px) {
#chat-nav {
width: 100%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 100;
transform: translateX(-100%);
transition: transform 0.3s ease;
}
#chat-nav.active {
transform: translateX(0);
}
#chat-content {
width: 100%;
}
.chat-header {
padding: 15px;
}
.chat-input-area {
padding: 10px 15px;
}
}
</style>

1353
src/Views/User/User.vue Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,28 +2,902 @@
<!-- 布局 从上到下 user信息用户头像 用户名 -->
<template>
<div class="user-info">
<!-- 用户信息头部 -->
<div class="user-info-top">
<div class="user-avatar">
<!-- <img :src="user.avatar" alt="用户头像"> -->
<div class="user-avatar-wrapper">
<div class="user-avatar">
<img :src="user.avatar" alt="用户头像" class="avatar-img">
<span class="avatar-edit-badge">编辑</span>
</div>
<!-- <span class="user-online-indicator"></span> -->
<div class="user-name">
<span class="name-text">{{ user.username }}</span>
<span class="user-level">Lv.{{ user.level }}</span>
</div>
</div>
<div class="user-name">
<div>用户名</div>
<div>关注店铺 收货地址</div>
<div class="user-name-section">
<div class="user-stats">
<div class="stat-item">
<span class="stat-value">{{ user.followCount }}</span>
<span class="stat-label">关注</span>
</div>
<div class="stat-divider"></div>
<div class="stat-item">
<span class="stat-value">{{ user.fansCount }}</span>
<span class="stat-label">粉丝</span>
</div>
<div class="stat-divider"></div>
<div class="stat-item">
<span class="stat-value">{{ user.collectionCount }}</span>
<span class="stat-label">收藏</span>
</div>
</div>
<div class="user-actions">
<a href="/user/address" class="action-link">收货地址</a>
<a href="/user/follow" class="action-link">关注店铺</a>
</div>
</div>
</div>
<div class="user-info-main">
<div>
购物信息 购物车 待收货 代发货 待付款
<!-- 订单状态卡片 -->
<div class="order-status-card">
<div class="card-header">
<h3 class="card-title">我的订单</h3>
<!-- <a href="/user/orders" class="card-more">查看全部 <SettingOutlined style="transform: rotate(90deg);" /></a> -->
</div>
<div>
订单信息 已完成 待评价 待付款 待发货
<div class="order-status-grid">
<div class="status-item" @click="navigateToOrder('pending_payment')">
<div class="status-icon">
<CreditCardOutlined />
</div>
<div class="status-label">待付款</div>
<div class="status-badge" v-if="orderCounts.pending_payment > 0">{{ orderCounts.pending_payment }}</div>
</div>
<div class="status-item" @click="navigateToOrder('pending_shipment')">
<div class="status-icon">
<LoadingOutlined />
</div>
<div class="status-label">待发货</div>
<div class="status-badge" v-if="orderCounts.pending_shipment > 0">{{ orderCounts.pending_shipment }}</div>
</div>
<div class="status-item" @click="navigateToOrder('pending_receipt')">
<div class="status-icon">
<CarOutlined />
</div>
<div class="status-label">待收货</div>
<div class="status-badge" v-if="orderCounts.pending_receipt > 0">{{ orderCounts.pending_receipt }}</div>
</div>
<div class="status-item" @click="navigateToOrder('pending_review')">
<div class="status-icon">
<SolutionOutlined />
</div>
<div class="status-label">待评价</div>
<div class="status-badge" v-if="orderCounts.pending_review > 0">{{ orderCounts.pending_review }}</div>
</div>
<div class="status-item" @click="navigateToOrder('completed')">
<div class="status-icon">
<CheckOutlined />
</div>
<div class="status-label">已完成</div>
</div>
</div>
<div>
优惠 红包 优惠卷 淘币
</div>
<!-- 功能菜单网格 -->
<div class="user-function-grid">
<!-- 购物相关 -->
<div class="function-card">
<div class="card-header">
<h3 class="card-title">购物相关</h3>
</div>
<div class="function-grid">
<div class="function-item" @click="navigateTo('/cart')">
<div class="function-icon">
<ShoppingCartOutlined />
</div>
<div class="function-label">购物车</div>
</div>
<div class="function-item" @click="navigateTo('/user/wishlist')">
<div class="function-icon">
<HeartOutlined />
</div>
<div class="function-label">收藏夹</div>
</div>
<div class="function-item" @click="navigateTo('/user/history')">
<div class="function-icon">
<HistoryOutlined />
</div>
<div class="function-label">浏览历史</div>
</div>
<div class="function-item" @click="navigateTo('/user/followed_shops')">
<div class="function-icon">
<ShopOutlined />
</div>
<div class="function-label">关注店铺</div>
</div>
</div>
</div>
<div>
足迹信息 已买完 收藏夹 购买过的店 足迹信息
<!-- 优惠相关 -->
<div class="function-card">
<div class="card-header">
<h3 class="card-title">优惠相关</h3>
</div>
<div class="function-grid">
<div class="function-item" @click="navigateTo('/user/coupons')">
<div class="function-icon">
<GiftOutlined />
</div>
<div class="function-label">红包</div>
<div class="function-badge" v-if="user.couponCount > 0">{{ user.couponCount }}</div>
</div>
<div class="function-item" @click="navigateTo('/user/discounts')">
<div class="function-icon">
<TagOutlined />
</div>
<div class="function-label">优惠券</div>
<div class="function-badge" v-if="user.discountCount > 0">{{ user.discountCount }}</div>
</div>
<div class="function-item" @click="navigateTo('/user/tao_coin')">
<div class="function-icon">
<GoldOutlined />
</div>
<div class="function-label">淘币</div>
<div class="function-value">{{ user.taoCoin }}</div>
</div>
<div class="function-item" @click="navigateTo('/user/points')">
<div class="function-icon">
<TrophyOutlined />
</div>
<div class="function-label">积分</div>
<div class="function-value">{{ user.points }}</div>
</div>
</div>
</div>
<!-- 账户相关 -->
<div class="function-card">
<div class="card-header">
<h3 class="card-title">账户相关</h3>
</div>
<div class="function-grid">
<div class="function-item" @click="navigateTo('/user/profile')">
<div class="function-icon">
<SettingOutlined />
</div>
<div class="function-label">账户设置</div>
</div>
<div class="function-item" @click="navigateTo('/user/address')">
<div class="function-icon">
<EnvironmentOutlined />
</div>
<div class="function-label">收货地址</div>
</div>
<div class="function-item" @click="navigateTo('/user/customer_service')">
<div class="function-icon">
<CustomerServiceOutlined />
</div>
<div class="function-label">客服中心</div>
</div>
<div class="function-item" @click="navigateTo('/user/help')">
<div class="function-icon">
<QuestionCircleOutlined />
</div>
<div class="function-label">帮助中心</div>
</div>
</div>
</div>
</div>
</div>
</template>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { ShoppingCartOutlined, HeartOutlined, HistoryOutlined, ShopOutlined, GiftOutlined, GoldOutlined, TrophyOutlined, SettingOutlined, EnvironmentOutlined, CustomerServiceOutlined, QuestionCircleOutlined, CreditCardOutlined, CarOutlined, LoadingOutlined, CheckOutlined, SolutionOutlined, TagOutlined } from '@ant-design/icons-vue'
const router = useRouter()
// 用户信息
const user = ref({
username: '用户名',
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=user123',
level: 3,
followCount: 12,
fansCount: 8,
collectionCount: 25,
couponCount: 3,
discountCount: 5,
taoCoin: 1280,
points: 560
})
// 订单状态数量
const orderCounts = ref({
pending_payment: 2,
pending_shipment: 1,
pending_receipt: 3,
pending_review: 0,
completed: 0
})
// 导航到指定页面
const navigateTo = (path: string) => {
// 根据路径跳转到User.vue中对应的导航项
if (path === '/user/address') {
router.push({ path: '/user', query: { nav: 'address' } })
} else if (path === '/user/wishlist' || path === '/user/favorite') {
router.push({ path: '/user', query: { nav: 'favorite' } })
} else if (path === '/user/customer_service') {
router.push({ path: '/user', query: { nav: 'customerService' } })
} else if (path === '/user/help') {
router.push({ path: '/user', query: { nav: 'help' } })
} else if (path === '/user/profile' || path === '/user/settings') {
router.push({ path: '/user', query: { nav: 'userInfo' } })
} else {
// 其他路径保持不变
router.push(path)
}
}
// 导航到订单页面并带上状态参数
const navigateToOrder = (status: string) => {
router.push({
path: '/user',
query: {
nav: 'order',
status: status
}
})
}
</script>
<style scoped>
.user-info {
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
position: relative;
}
/* 用户信息头部 */
.user-info-top {
align-items: center;
background: linear-gradient(135deg, #ff6b6b 0%, #4ecdc4 50%, #45b7d1 100%);
border-radius: 16px;
padding: 10px;
margin-bottom: 30px;
color: #ffffff;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
position: relative;
overflow: hidden;
}
.user-info-top::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 100%);
pointer-events: none;
}
.user-avatar-wrapper {
display: flex;
position: relative;
}
.user-avatar {
position: relative;
width: 60px;
height: 60px;
border-radius: 50%;
overflow: hidden;
border: 4px solid rgba(255, 255, 255, 0.3);
transition: all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
margin-right: 12px;
}
.user-avatar:hover {
transform: scale(1.1) rotate(360deg);
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);
border-color: rgba(255, 255, 255, 0.8);
}
.avatar-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.avatar-edit-badge {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.6);
color: #ffffff;
font-size: 6px;
padding: 4px 0;
text-align: center;
transition: all 0.3s ease;
}
.user-online-indicator {
position: absolute;
bottom: 0;
right: 0;
width: 14px;
height: 14px;
background-color: #52c41a;
border: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
box-shadow: 0 2px 8px rgba(82, 196, 26, 0.4);
animation: pulse 2s infinite;
}
.user-name-section {
padding: 0 12px;
flex: 1;
}
.user-name {
display: flex;
align-items: center;
padding: 8px 12px;
border-radius: 16px;
backdrop-filter: blur(10px);
}
.name-text {
font-size: 12px;
font-weight: 700;
margin-right: 12px;
}
.user-level {
font-size: 14px;
font-weight: 600;
background-color: rgba(255, 255, 255, 0.2);
padding: 4px 12px;
border-radius: 16px;
backdrop-filter: blur(10px);
}
.user-stats {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 16px;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 24px;
}
.stat-value {
font-size: 18px;
font-weight: 600;
margin-bottom: 4px;
}
.stat-label {
font-size: 12px;
opacity: 0.9;
}
.stat-divider {
width: 1px;
height: 30px;
background-color: rgba(255, 255, 255, 0.3);
margin: 0 16px;
}
.user-actions {
display: flex;
justify-content: center;
gap: 12px;
}
.action-link {
color: #ffffff;
text-decoration: none;
font-size: 14px;
padding: 6px 16px;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
backdrop-filter: blur(10px);
}
.action-link:hover {
background-color: rgba(255, 255, 255, 0.3);
transform: translateY(-2px) scale(1.05);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
backdrop-filter: blur(15px);
}
/* 订单状态卡片 */
.order-status-card {
background-color: #ffffff;
border-radius: 12px;
padding: 10px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 1px solid rgba(0, 0, 0, 0.05);
margin-top: 45px;
}
.order-status-card:hover {
transform: translateY(-2px);
border-color: rgba(255, 107, 107, 0.2);
}
.order-status-card .card-header {
background: linear-gradient(90deg, #ff9ff3 0%, #feca57 100%);
color: white;
padding: 12px 16px;
border-radius: 8px 8px 0 0;
margin: -10px -10px 5px -10px;
}
.order-status-card .card-title {
color: white;
}
.order-status-card .card-more {
color: rgba(255, 255, 255, 0.9);
}
.order-status-card .card-more:hover {
color: white;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #333333;
margin: 0;
}
.card-more {
font-size: 14px;
color: #666666;
text-decoration: none;
display: flex;
align-items: center;
gap: 4px;
transition: all 0.3s ease;
}
.card-more:hover {
color: #ff5000;
}
.order-status-grid {
display: flex;
justify-content: center;
}
.status-item {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
padding: 16px 4px;
border-radius: 8px;
position: relative;
}
.status-item:hover {
background-color: #f8f9fa;
transform: translateY(-2px);
}
.status-icon {
width: 38px;
height: 38px;
border-radius: 50%;
background-color: #f0f2f5;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
font-size: 24px;
color: #666666;
transition: all 0.3s ease;
}
.status-item:hover .status-icon {
background-color: rgba(255, 107, 107, 0.1);
color: #ff6b6b;
transform: scale(1.1) rotate(5deg);
box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3);
}
.status-label {
font-size: 8px;
color: #333333;
margin-bottom: 4px;
transition: all 0.3s ease;
}
.status-item:hover .status-label {
color: #ff6b6b;
transform: translateY(-2px);
}
.status-badge {
position: absolute;
top: 8px;
right: 8px;
background-color: #ff4d4f;
color: #ffffff;
font-size: 12px;
font-weight: 600;
padding: 2px 8px;
border-radius: 10px;
min-width: 20px;
text-align: center;
}
/* 功能菜单网格 */
.user-function-grid {
position: absolute;
left: -300%;
top: 0;
display: flex;
flex-direction: row;
gap: 16px;
background-color: #ffffff;
border-radius: 12px;
padding: 20px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
z-index: 10;
opacity: 0;
visibility: hidden;
transition: all 1s ease;
}
.user-info:hover .user-function-grid {
opacity: 1;
visibility: visible;
left: -215%;
}
.function-card {
background-color: #ffffff;
border-radius: 12px;
padding: 16px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 1px solid rgba(0, 0, 0, 0.05);
width: 160px;
flex-shrink: 0;
}
/* 调整user-info的宽度确保左侧有足够空间显示功能菜单 */
.user-info {
width: 100%;
min-width: 200px;
}
/* 调整功能网格布局,使其在窄列中更紧凑 */
.function-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.function-card:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
border-color: rgba(255, 107, 107, 0.2);
}
/* 功能卡片头部公共样式 */
.function-card .card-header {
color: white;
padding: 12px 16px;
border-radius: 8px 8px 0 0;
margin: -16px -16px 16px -16px;
}
.function-card .card-title {
color: white;
}
/* 购物相关卡片 */
.function-card:nth-child(1) .card-header {
background: linear-gradient(90deg, #ff6b6b 0%, #ff8e53 100%);
}
/* 优惠相关卡片 */
.function-card:nth-child(2) .card-header {
background: linear-gradient(90deg, #4ecdc4 0%, #45b7d1 100%);
}
/* 账户相关卡片 */
.function-card:nth-child(3) .card-header {
background: linear-gradient(90deg, #96ceb4 0%, #feca57 100%);
}
.function-item {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
padding: 12px 4px;
border-radius: 8px;
position: relative;
}
.function-item:hover {
background-color: #f8f9fa;
transform: translateY(-2px);
}
.function-icon {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #f0f2f5;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 6px;
font-size: 20px;
color: #666666;
transition: all 0.3s ease;
}
.function-item:hover .function-icon {
background-color: rgba(78, 205, 196, 0.1);
color: #4ecdc4;
transform: scale(1.1) rotate(5deg);
box-shadow: 0 4px 12px rgba(78, 205, 196, 0.3);
}
.function-label {
font-size: 12px;
color: #333333;
margin-bottom: 2px;
transition: all 0.3s ease;
}
.function-item:hover .function-label {
color: #4ecdc4;
transform: translateY(-2px);
}
.function-badge {
position: absolute;
top: 8px;
right: 8px;
background-color: #ff4d4f;
color: #ffffff;
font-size: 12px;
font-weight: 600;
padding: 2px 8px;
border-radius: 10px;
min-width: 20px;
text-align: center;
}
.function-value {
font-size: 12px;
color: #ff5000;
font-weight: 600;
}
/* 动画效果 */
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.7);
}
70% {
box-shadow: 0 0 0 10px rgba(82, 196, 26, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(82, 196, 26, 0);
}
}
/* 响应式设计 */
@media (max-width: 768px) {
.user-info {
padding: 12px;
}
.user-info-top {
flex-direction: column;
text-align: center;
padding: 20px;
}
.user-avatar-wrapper {
margin-right: 0;
margin-bottom: 20px;
}
.user-stats {
justify-content: center;
flex-wrap: wrap;
}
.stat-item {
margin-right: 16px;
}
.user-actions {
justify-content: center;
flex-wrap: wrap;
}
.order-status-grid {
grid-template-columns: repeat(5, 1fr);
gap: 8px;
}
.status-item {
padding: 12px 4px;
}
.status-icon {
width: 40px;
height: 40px;
font-size: 20px;
}
.status-label {
font-size: 12px;
}
.user-function-grid {
grid-template-columns: 1fr;
gap: 16px;
}
.function-grid {
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.function-item {
padding: 12px 4px;
}
.function-icon {
width: 40px;
height: 40px;
font-size: 20px;
}
.function-label {
font-size: 12px;
}
/* 调整卡片头部样式 */
.function-card .card-header {
padding: 10px 12px;
margin: -16px -16px 16px -16px;
}
.function-card {
padding: 16px;
}
.order-status-card {
padding: 16px;
}
.order-status-card .card-header {
padding: 10px 12px;
margin: -16px -16px 16px -16px;
}
}
@media (max-width: 576px) {
.user-info-top {
padding: 16px;
}
.user-avatar {
width: 80px;
height: 80px;
}
.name-text {
font-size: 20px;
}
.user-stats {
gap: 12px;
}
.stat-item {
margin-right: 12px;
}
.order-status-grid {
grid-template-columns: repeat(5, 1fr);
gap: 4px;
}
.status-item {
padding: 8px 2px;
}
.status-icon {
width: 32px;
height: 32px;
font-size: 16px;
}
.status-label {
font-size: 10px;
}
.function-grid {
grid-template-columns: repeat(4, 1fr);
gap: 4px;
}
.function-item {
padding: 8px 2px;
}
.function-icon {
width: 32px;
height: 32px;
font-size: 16px;
}
.function-label {
font-size: 10px;
}
}
@media (max-width: 375px) {
.order-status-grid {
grid-template-columns: repeat(5, 1fr);
}
.status-item {
padding: 6px 2px;
}
.status-icon {
width: 28px;
height: 28px;
font-size: 14px;
}
.function-grid {
grid-template-columns: repeat(4, 1fr);
}
.function-item {
padding: 6px 2px;
}
.function-icon {
width: 28px;
height: 28px;
font-size: 14px;
}
}
</style>

View File

@@ -6,7 +6,19 @@
</div>
<div id="footer-copyright">
<!-- 版权信息 -->
<h2>Copyright @ 2023 淘淘王</h2>
<div class="copyright-content">
<p class="copyright-text">© 2026 TaoTaoWang. 保留所有权利</p>
<div class="copyright-links">
<a href="/about">关于我们</a>
<span class="copyright-separator">|</span>
<a href="/privacy">隐私政策</a>
<span class="copyright-separator">|</span>
<a href="/terms">服务条款</a>
<span class="copyright-separator">|</span>
<a href="/contact">联系我们</a>
</div>
<p class="copyright-icp">京ICP备12345678号-1 | 京公网安备11010502030123号</p>
</div>
</div>
</div>
</template>
@@ -59,7 +71,7 @@ const productLists = ref([
<style scoped>
#footer {
width: 100%;
padding: 0 20px;
padding: 0 var(--spacing-md);
}
h1 {
color: #42b983;
@@ -69,4 +81,74 @@ h1 {
/* 高度根据内容自适应 */
height: initial;
}
/* 版权信息样式 */
#footer-copyright {
background-color: var(--bg-light);
padding: var(--spacing-md) 0;
border-top: 1px solid var(--border-light);
margin-top: var(--spacing-xl);
}
.copyright-content {
max-width: 1200px;
margin: 0 auto;
text-align: center;
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
.copyright-text {
margin: 0 0 var(--spacing-sm) 0;
font-weight: 500;
color: var(--text-primary);
}
.copyright-links {
margin: 0 0 var(--spacing-sm) 0;
}
.copyright-links a {
color: var(--text-secondary);
text-decoration: none;
margin: 0 var(--spacing-sm);
transition: color var(--transition-normal);
}
.copyright-links a:hover {
color: #ff5000;
}
.copyright-separator {
color: #999;
margin: 0 4px;
}
.copyright-icp {
margin: 0;
font-size: 12px;
color: #999;
}
/* 响应式调整 */
@media (max-width: 768px) {
.copyright-content {
padding: 0 20px;
}
.copyright-links {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
}
.copyright-links a {
margin: 0;
}
.copyright-separator {
display: none;
}
}
</style>

View File

@@ -5,8 +5,14 @@
<!-- 用户信息悬浮菜单 -->
<Dropdown :menu="{ items: userMenu }" trigger="hover">
<div class="user-info-container">
<Avatar size="large" src="https://api.dicebear.com/7.x/avataaars/svg?seed=user123" />
<span class="user-name">用户名</span>
<div class="user-avatar-wrapper">
<Avatar size="large" src="https://api.dicebear.com/7.x/avataaars/svg?seed=user123" class="user-avatar" />
<span class="user-online-indicator"></span>
</div>
<div class="user-info-text">
<span class="user-name">用户名</span>
<span class="user-level">Lv.3</span>
</div>
<span class="user-arrow"></span>
</div>
</Dropdown>
@@ -14,11 +20,15 @@
<div id="header-profile-right">
<!-- 右侧功能菜单 -->
<Dropdown :menu="{ items: rightMenu }" trigger="hover">
<Button type="text">更多</Button>
<Button type="text" class="header-more-btn">更多 <i class="iconfont icon-zhankaishouqi"></i></Button>
</Dropdown>
<a href="/">首页</a>
<Button type="primary" @click="router.push('/cart')">购物车</Button>
<Button type="primary" @click="router.push('/order')">订单</Button>
<a href="/" class="header-nav-link">首页</a>
<Button type="primary" @click="router.push('/cart')" class="header-cart-btn">
<i class="iconfont icon-gouwuche"></i> 购物车
</Button>
<Button type="primary" @click="router.push('/order')" class="header-order-btn">
<i class="iconfont icon-dingdan"></i> 订单
</Button>
</div>
</div>
<Row id="header-nav-row" v-if="booleanSearch">
@@ -31,30 +41,23 @@
<!-- 搜索类型选择 -->
<div class="search-type-selector">
<ul>
<li class="search-type-item active" @click="setSearchType('宝贝')">宝贝</li>
<li class="search-type-item" @click="setSearchType('店铺')">店铺</li>
<li class="search-type-item active" @click="setSearchType('宝贝', $event)">宝贝</li>
<li class="search-type-item" @click="setSearchType('店铺', $event)">店铺</li>
</ul>
</div>
<!-- 搜索输入区域 -->
<div class="search-input-wrapper">
<div class="search-input-prefix">
<i class="iconfont icon-sousuo prefix-icon"></i>
</div>
<Input
v-model:value="searchValue"
placeholder="请输入搜索关键词"
style="width: 100%"
@search="onSearch"
@focus="onInputFocus"
@blur="onInputBlur"
class="custom-search-input"
/>
<Input v-model:value="searchValue" placeholder="请输入搜索关键词" style="width: 100%" @search="onSearch"
@focus="onInputFocus" @blur="onInputBlur" class="custom-search-input" />
<div class="search-input-suffix" v-if="searchValue">
<i class="iconfont icon-guanbi" @click="clearSearch"></i>
</div>
</div>
<!-- 搜索按钮 -->
<div class="search-button-container" @onclick="onSearch">
<span class="search-button-text">搜索</span>
@@ -100,7 +103,7 @@ const searchValue = ref('')
const showHistory = ref(false)
// 标志:是否正在清空历史记录
const isClearingHistory = ref(false)
// 标志:是否在搜索界面
// 控制搜索框是否显示
const booleanSearch = ref(true)
// 路由事件
router.beforeEach((to, from, next) => {
@@ -109,7 +112,7 @@ router.beforeEach((to, from, next) => {
}
console.log(to.name)
// 如果在商品页面 隐藏搜索框
if (to.name === 'productDetail') {
if (to.name === 'productDetail' || to.name === 'chat') {
booleanSearch.value = false
} else {
booleanSearch.value = true
@@ -173,15 +176,56 @@ const onInputBlur = () => {
}, 200)
}
// 当前搜索类型
const currentSearchType = ref('宝贝')
// 设置搜索类型
const setSearchType = (type: string) => {
const setSearchType = (type: string, event: MouseEvent) => {
const typeItems = document.querySelectorAll('.search-type-item')
typeItems.forEach(item => {
item.classList.remove('active')
})
// 添加active类到点击的元素
// event?.currentTarget?.classList.add('active')
console.log('搜索类型:', type)
// 找到当前活跃的元素
const currentActiveItem = document.querySelector('.search-type-item.active')
// 保存点击的元素引用
const clickedTarget = event.currentTarget as HTMLElement
// 为当前活跃的元素添加消失动画
if (currentActiveItem && currentActiveItem !== clickedTarget) {
if (currentSearchType.value === '宝贝' && type === '店铺') {
// 宝贝 -> 店铺:宝贝元素从左往右消失
currentActiveItem.classList.add('animate-right-out')
} else if (currentSearchType.value === '店铺' && type === '宝贝') {
// 店铺 -> 宝贝:店铺元素从右往左消失
currentActiveItem.classList.add('animate-left-out')
}
// 等待消失动画完成后再继续
setTimeout(() => {
// 移除所有元素的类
typeItems.forEach(item => {
item.classList.remove('active', 'animate-left', 'animate-right', 'animate-left-out', 'animate-right-out')
})
// 添加active类到点击的元素
if (clickedTarget) {
// 判断切换方向
if (currentSearchType.value === '宝贝' && type === '店铺') {
// 宝贝 -> 店铺:从左往右出现
clickedTarget.classList.add('active', 'animate-right')
} else if (currentSearchType.value === '店铺' && type === '宝贝') {
// 店铺 -> 宝贝:从右往左出现
clickedTarget.classList.add('active', 'animate-left')
} else {
// 默认动画
clickedTarget.classList.add('active')
}
currentSearchType.value = type
}
console.log('搜索类型:', type)
}, 300)
} else {
// 如果点击的是当前活跃的元素,直接返回
return
}
}
// 清除搜索输入
@@ -226,8 +270,8 @@ const rightMenu = [
<style scoped>
#header {
width: 100%;
background-color: #ffffff;
padding: 10px 20px;
background-color: var(--card-bg);
padding: var(--spacing-sm) var(--spacing-md);
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */
position: relative;
z-index: 1000;
@@ -242,7 +286,6 @@ const rightMenu = [
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
}
#header-profile-left {
@@ -255,38 +298,290 @@ const rightMenu = [
display: flex;
justify-content: flex-end;
align-items: center;
gap: 10px;
gap: var(--spacing-md);
}
/* 用户信息容器样式 */
.user-info-container {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-radius: 20px;
gap: var(--spacing-md);
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--border-radius-3xl);
cursor: pointer;
transition: all 0.3s ease;
transition: all var(--transition-transform);
background-color: var(--card-bg);
box-shadow: var(--shadow-sm);
}
.user-info-container:hover {
background-color: #f0f2f5;
background-color: var(--bg-light);
box-shadow: var(--shadow-md);
transform: translateY(-1px);
}
/* 用户头像区域 */
.user-avatar-wrapper {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.user-avatar {
border: 2px solid #ffffff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.user-info-container:hover .user-avatar {
transform: scale(1.05);
}
.user-online-indicator {
position: absolute;
bottom: 0;
right: 0;
width: 10px;
height: 10px;
background-color: var(--success-color);
border: 2px solid var(--card-bg);
border-radius: var(--border-radius-full);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.7);
}
70% {
box-shadow: 0 0 0 10px rgba(82, 196, 26, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(82, 196, 26, 0);
}
}
/* 用户信息文本区域 */
.user-info-text {
display: flex;
flex-direction: column;
gap: 2px;
}
.user-name {
font-size: 14px;
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--text-primary);
line-height: 1.2;
}
.user-level {
font-size: var(--font-size-xs);
font-weight: 500;
color: #333;
color: var(--warning-color);
background-color: #fff7e6;
padding: 1px 6px;
border-radius: var(--border-radius-xl);
align-self: flex-start;
}
.user-arrow {
font-size: 12px;
color: #999;
transition: transform 0.3s ease;
font-size: var(--font-size-xs);
color: var(--text-tertiary);
transition: transform var(--transition-transform);
}
.user-info-container:hover .user-arrow {
transform: rotate(180deg);
transform: rotate(180deg) scale(1.1);
color: var(--text-secondary);
}
/* 右侧功能菜单样式 */
.header-more-btn {
display: flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-xs) var(--spacing-md);
border-radius: var(--border-radius-2xl);
transition: all var(--transition-transform);
font-size: var(--font-size-sm);
}
.header-more-btn:hover {
background-color: var(--bg-color);
color: var(--text-primary);
}
.header-nav-link {
font-size: var(--font-size-sm);
font-weight: 500;
color: var(--text-secondary);
text-decoration: none;
padding: var(--spacing-xs) var(--spacing-md);
border-radius: var(--border-radius-2xl);
transition: all var(--transition-transform);
position: relative;
}
.header-nav-link:hover {
color: var(--primary-color);
background-color: var(--bg-primary-lightest);
}
.header-nav-link::after {
content: '';
position: absolute;
bottom: 2px;
left: 50%;
width: 0;
height: 2px;
background-color: var(--primary-color);
border-radius: 1px;
transition: all var(--transition-transform);
}
.header-nav-link:hover::after {
width: 80%;
left: 10%;
}
/* 购物车和订单按钮样式 */
.header-cart-btn,
.header-order-btn {
display: flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--border-radius-3xl);
font-size: var(--font-size-sm);
font-weight: 500;
transition: all var(--transition-transform);
position: relative;
overflow: hidden;
}
.header-cart-btn {
background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
border: none;
}
.header-order-btn {
background: linear-gradient(135deg, var(--secondary-color), var(--secondary-hover));
border: none;
}
.header-cart-btn:hover,
.header-order-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
}
.header-cart-btn:active,
.header-order-btn:active {
transform: translateY(0);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.header-cart-btn::before,
.header-order-btn::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transform: rotate(45deg);
animation: shine 3s ease-in-out infinite;
}
@keyframes shine {
0% {
transform: rotate(45deg) translateX(-100%) translateY(-100%);
opacity: 0;
}
50% {
opacity: 0.8;
}
100% {
transform: rotate(45deg) translateX(100%) translateY(100%);
opacity: 0;
}
}
/* 响应式设计 */
@media (max-width: 768px) {
#header-profile {
padding: 8px 0;
}
.user-info-container {
gap: 8px;
padding: 8px 12px;
}
.user-name {
font-size: 13px;
}
.user-level {
font-size: 11px;
padding: 1px 4px;
}
#header-profile-right {
gap: 8px;
}
.header-nav-link {
font-size: 13px;
padding: 4px 8px;
}
.header-cart-btn,
.header-order-btn {
padding: 6px 12px;
font-size: 13px;
}
.header-cart-btn i,
.header-order-btn i,
.header-more-btn i {
font-size: 14px;
}
}
@media (max-width: 576px) {
.user-info-text {
display: none;
}
.user-info-container {
padding: 6px;
border-radius: 50%;
}
.header-nav-link {
font-size: 12px;
}
.header-cart-btn span,
.header-order-btn span {
display: none;
}
.header-cart-btn,
.header-order-btn {
padding: 8px;
border-radius: 50%;
min-width: unset;
}
}
/* Logo样式 */
@@ -311,7 +606,7 @@ const rightMenu = [
align-items: flex-start;
position: relative;
width: 100%;
max-width: 700px;
max-width: 800px;
margin: 0 auto;
}
@@ -394,22 +689,81 @@ const rightMenu = [
content: '';
position: absolute;
bottom: 8px;
left: 0;
width: 100%;
left: -10%;
width: 120%;
height: 2px;
background-color: #ff5000;
border-radius: 1px;
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
/* 从左往右动画 */
.search-type-item.animate-right::after {
animation: slideInRight 0.3s ease-out;
}
/* 从右往左动画 */
.search-type-item.animate-left::after {
animation: slideInLeft 0.3s ease-out;
}
/* 从左往右消失动画 */
.search-type-item.animate-right-out::after {
animation: slideOutRight 0.3s ease-out;
}
/* 从右往左消失动画 */
.search-type-item.animate-left-out::after {
animation: slideOutLeft 0.3s ease-out;
}
/* 搜索类型选择器从左往右动画 */
@keyframes slideInRight {
from {
width: 0;
left: 50%;
left: -10%;
}
to {
width: 100%;
left: 0;
width: 120%;
left: -10%;
}
}
/* 搜索类型选择器从右往左动画 */
@keyframes slideInLeft {
from {
width: 0;
left: 120%;
}
to {
width: 120%;
left: -10%;
}
}
/* 从左往右消失动画 */
@keyframes slideOutRight {
from {
width: 120%;
left: -10%;
}
to {
width: 0;
left: 100%;
}
}
/* 从右往左消失动画 */
@keyframes slideOutLeft {
from {
width: 10%;
right: 0;
}
to {
width: 0%;
right: 100%;
}
}
@@ -442,15 +796,17 @@ const rightMenu = [
font-size: 16px;
min-height: 52px;
height: 52px;
padding: 0 50px 0 48px;
padding: 0 25px 0 15px;
border: none;
box-shadow: none;
background-color: transparent;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
font-weight: 400;
letter-spacing: 0.5px;
box-sizing: border-box; /* 关键! */
outline: none; /* 避免默认焦点轮廓 */
box-sizing: border-box;
/* 关键! */
outline: none;
/* 避免默认焦点轮廓 */
}
/* 可选:焦点状态 */
@@ -499,6 +855,7 @@ const rightMenu = [
opacity: 0;
transform: translateY(-50%) scale(0.8);
}
to {
opacity: 1;
transform: translateY(-50%) scale(1);
@@ -517,8 +874,7 @@ const rightMenu = [
/* 搜索按钮 */
.search-button-container {
margin-right: 1px;
padding: 15.5px;
padding: 16.5px 30px;
height: 100%;
background: linear-gradient(135deg, #ff5000, #ff8c00);
color: #ffffff;
@@ -597,42 +953,42 @@ const rightMenu = [
.search-type-selector {
padding: 0 12px;
}
.search-type-selector ul {
gap: 12px;
}
.search-type-item {
padding: 12px 0;
font-size: 13px;
}
.search-input-wrapper {
padding: 0 12px;
}
.custom-search-input {
font-size: 14px !important;
height: 48px !important;
padding: 0 40px 0 40px !important;
}
.search-input-prefix {
font-size: 16px;
}
.search-button-container {
padding: 0 24px;
}
.search-button-text {
font-size: 14px;
}
.search-button-icon {
font-size: 14px;
}
.search-button-container:hover .search-button-icon {
transform: scale(1.05) rotate(10deg);
}
@@ -642,36 +998,36 @@ const rightMenu = [
.search-type-selector {
padding: 0 10px;
}
.search-type-selector ul {
gap: 8px;
}
.search-type-item {
font-size: 12px;
}
.search-input-wrapper {
padding: 0 10px;
}
.custom-search-input {
font-size: 13px !important;
padding: 0 35px 0 35px !important;
}
.search-input-prefix {
font-size: 14px;
}
.search-button-container {
padding: 0 20px;
}
.search-button-text {
font-size: 13px;
}
.search-button-icon {
display: none;
}

View File

@@ -83,7 +83,7 @@ const adList = [
<style scoped>
#main {
width: 100%;
padding: 0 20px;
padding: 0 var(--spacing-md);
}
h1 {
@@ -95,8 +95,8 @@ h1 {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
padding: 16px 0;
gap: var(--spacing-md);
padding: var(--spacing-md) 0;
width: 100%;
flex-wrap: wrap;
}
@@ -128,17 +128,17 @@ h1 {
}
/* 商品分类样式 */
.main-content-col-top {
padding: 20px;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
padding: var(--spacing-md);
background-color: var(--card-bg);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-lg);
position: relative;
z-index: 100;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
transition: all var(--transition-transform);
}
.main-content-col-top:hover {
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
box-shadow: var(--shadow-xl);
}
@@ -161,36 +161,35 @@ h1 {
}
.main-content-col-top li {
margin-bottom: 12px;
padding: 8px;
border-radius: 8px;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
margin-bottom: var(--spacing-sm);
padding: var(--spacing-sm);
border-radius: var(--border-radius-md);
transition: all var(--transition-transform);
position: relative;
overflow: visible;
}
/* 分类详情样式 */
.main-content-col-top li:hover {
background-color: #fff5f5;
transform: translateX(8px);
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.1);
background-color: var(--bg-primary-light);
transform: translateX(var(--spacing-sm));
box-shadow: 0 2px 8px rgba(var(--primary-light-rgb), 0.1);
}
/* 分类项样式 */
.category-item {
display: flex;
align-items: center;
gap: 5px;
gap: var(--spacing-xs);
position: relative;
cursor: pointer;
padding: 12px;
border-radius: 8px;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border-radius: var(--border-radius-md);
transition: all var(--transition-transform);
}
.category-item:hover {
/* .category-item:hover {
background-color: rgba(255, 80, 0, 0.05);
}
} */
/* 分类详情样式 */
.category-detail {
@@ -199,17 +198,17 @@ h1 {
top: -60px;
width: 600px;
height: 400px;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
padding: 20px;
margin-left: 10px;
background-color: var(--card-bg);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-xl);
padding: var(--spacing-md);
margin-left: var(--spacing-sm);
z-index: 9999;
opacity: 0;
visibility: hidden;
transform: translateX(-20px);
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 2px solid #f0f0f0;
transition: all var(--transition-transform);
border: 2px solid var(--border-color);
overflow-x: auto;
}
@@ -363,6 +362,7 @@ h1 {
/* 轮播广告样式 */
#carousel-container {
width: 100%;
height: 100%;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
@@ -371,7 +371,7 @@ h1 {
.carousel-item {
position: relative;
width: 100%;
height: 300px;
height: 100%;
overflow: hidden;
}
@@ -419,20 +419,5 @@ h1 {
/* 个人信息样式 */
.main-content-col-bottom {
padding: 20px;
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.main-content-col-bottom h2 {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0;
padding: 16px;
background-color: #fafafa;
border-radius: 6px;
text-align: center;
}
</style>