- 为控制台首页添加页面标题动态设置 - 为应用中心页面添加页面标题动态设置 - 修改控制台布局,实现动态浏览器标签页标题更新 - 新增“天天系统”ERP管理平台主页,包含侧边栏导航、顶部栏及数据概览模块 - 实现主页搜索框、通知、语言和用户信息区域交互 - 添加欢迎区、快捷入口、最近使用应用列表及应用详情抽屉功能 - 支持小程序扫码弹窗展示和应用类型图标及颜色区分 - 优化页面样式,支持响应式布局及交互效果 - 更新Nuxt国际化重定向路径片段标识符以兼容新版本
497 lines
20 KiB
Vue
497 lines
20 KiB
Vue
<template>
|
||
<div class="flex min-h-screen bg-gradient-to-br from-gray-50 to-gray-100">
|
||
<!-- 左侧导航 -->
|
||
<aside class="sidebar w-64 fixed h-full text-white flex flex-col">
|
||
<!-- Logo -->
|
||
<div class="p-6 border-b border-white/10">
|
||
<div class="flex items-center gap-3">
|
||
<div class="w-10 h-10 bg-white/20 rounded-xl flex items-center justify-center">
|
||
<BlockOutlined class="text-xl" />
|
||
</div>
|
||
<div>
|
||
<h1 class="font-bold text-lg">天天系统</h1>
|
||
<p class="text-xs text-white/70">ERP 管理平台</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 导航菜单 -->
|
||
<nav class="flex-1 py-6 px-3">
|
||
<div class="space-y-1">
|
||
<a href="#" class="sidebar-item active flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer" @click.prevent="activeMenu = 'home'">
|
||
<HomeOutlined class="text-base" />
|
||
<span>工作台</span>
|
||
</a>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer" @click.prevent="activeMenu = 'device'">
|
||
<SettingOutlined class="text-base" />
|
||
<span>设备管理</span>
|
||
</a>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer" @click.prevent="activeMenu = 'purchase'">
|
||
<ShoppingCartOutlined class="text-base" />
|
||
<span>采购管理</span>
|
||
</a>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer" @click.prevent="activeMenu = 'warehouse'">
|
||
<InboxOutlined class="text-base" />
|
||
<span>仓储物流</span>
|
||
</a>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer" @click.prevent="activeMenu = 'finance'">
|
||
<WalletOutlined class="text-base" />
|
||
<span>财务管理</span>
|
||
</a>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer" @click.prevent="activeMenu = 'hr'">
|
||
<TeamOutlined class="text-base" />
|
||
<span>人力资源</span>
|
||
</a>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer" @click.prevent="activeMenu = 'office'">
|
||
<ProjectOutlined class="text-base" />
|
||
<span>协同办公</span>
|
||
</a>
|
||
</div>
|
||
|
||
<div class="mt-8 pt-6 border-t border-white/10">
|
||
<p class="px-4 text-xs text-white/50 mb-3">个人</p>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer">
|
||
<UserOutlined class="text-base" />
|
||
<span>个人信息</span>
|
||
</a>
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer">
|
||
<SettingOutlined class="text-base" />
|
||
<span>系统设置</span>
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- 用户信息 -->
|
||
<div class="p-4 border-t border-white/10">
|
||
<div class="flex items-center gap-3">
|
||
<div class="w-10 h-10 bg-white/20 rounded-full flex items-center justify-center">
|
||
<UserOutlined />
|
||
</div>
|
||
<div class="flex-1">
|
||
<p class="font-medium">管理员</p>
|
||
<p class="text-xs text-white/70">超级管理员</p>
|
||
</div>
|
||
<button class="text-white/70 hover:text-white">
|
||
<LogoutOutlined />
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- 主内容区 -->
|
||
<main class="flex-1 ml-64">
|
||
<!-- 顶部栏 -->
|
||
<header class="bg-white/85 backdrop-blur-xl border-b border-white/20 sticky top-0 z-50 px-8 py-4">
|
||
<div class="flex items-center justify-between">
|
||
<!-- 搜索 -->
|
||
<div class="relative w-96">
|
||
<input
|
||
v-model="searchQuery"
|
||
type="text"
|
||
placeholder="🔍 搜索设备、订单、员工、文档..."
|
||
class="w-full px-5 py-3 bg-gray-100 rounded-xl border-0 focus:ring-2 focus:ring-purple-500 focus:bg-white transition-all"
|
||
>
|
||
</div>
|
||
|
||
<!-- 右侧 -->
|
||
<div class="flex items-center gap-6">
|
||
<!-- 全屏 -->
|
||
<button class="text-gray-500 hover:text-purple-600 transition-colors" @click="toggleFullscreen">
|
||
<ExpandOutlined class="text-lg" />
|
||
</button>
|
||
|
||
<!-- 消息 -->
|
||
<a-popover trigger="click">
|
||
<template #content>
|
||
<div class="w-64">
|
||
<div class="font-medium mb-2">通知中心</div>
|
||
<div class="text-sm text-gray-500">暂无新通知</div>
|
||
</div>
|
||
</template>
|
||
<button class="relative text-gray-500 hover:text-purple-600 transition-colors">
|
||
<Badge :count="3" :offset="[-2, 2]">
|
||
<BellOutlined class="text-lg" />
|
||
</Badge>
|
||
</button>
|
||
</a-popover>
|
||
|
||
<!-- 语言 -->
|
||
<button class="text-gray-500 hover:text-purple-600 transition-colors">
|
||
<GlobalOutlined class="text-lg" />
|
||
</button>
|
||
|
||
<!-- 用户 -->
|
||
<div class="flex items-center gap-3 pl-6 border-l border-gray-200">
|
||
<div class="w-10 h-10 bg-gradient-to-br from-purple-500 to-pink-500 rounded-xl flex items-center justify-center text-white font-bold">
|
||
A
|
||
</div>
|
||
<div>
|
||
<p class="font-medium text-gray-800">Admin</p>
|
||
<p class="text-xs text-gray-500">超级管理员</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- 内容区域 -->
|
||
<div class="p-8">
|
||
<!-- 欢迎区 -->
|
||
<div class="mb-8">
|
||
<h2 class="text-3xl font-bold text-gray-800 mb-2">
|
||
早上好,管理员!
|
||
</h2>
|
||
<p class="text-gray-500">今天是 {{ currentDate }},本周还有 <span class="text-purple-600 font-semibold">{{ remainingDays }}</span> 天工作日</p>
|
||
</div>
|
||
|
||
<!-- 数据概览 -->
|
||
<div class="grid grid-cols-4 gap-6 mb-8">
|
||
<div class="stat-card blue bg-white rounded-2xl p-6 card-hover shadow-sm">
|
||
<div class="flex items-center justify-between mb-4">
|
||
<div class="w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center">
|
||
<SettingOutlined class="text-blue-600 text-xl" />
|
||
</div>
|
||
<span class="text-green-500 text-sm font-medium flex items-center gap-1"><ArrowUpOutlined /> 12%</span>
|
||
</div>
|
||
<h3 class="text-3xl font-bold text-gray-800 mb-1">128</h3>
|
||
<p class="text-gray-500 text-sm">设备总数</p>
|
||
</div>
|
||
|
||
<div class="stat-card green bg-white rounded-2xl p-6 card-hover shadow-sm">
|
||
<div class="flex items-center justify-between mb-4">
|
||
<div class="w-12 h-12 bg-green-100 rounded-xl flex items-center justify-center">
|
||
<AppstoreOutlined class="text-green-600 text-xl" />
|
||
</div>
|
||
<span class="text-green-500 text-sm font-medium flex items-center gap-1"><ArrowUpOutlined /> 8%</span>
|
||
</div>
|
||
<h3 class="text-3xl font-bold text-gray-800 mb-1">5,230</h3>
|
||
<p class="text-gray-500 text-sm">库存物料</p>
|
||
</div>
|
||
|
||
<div class="stat-card orange bg-white rounded-2xl p-6 card-hover shadow-sm">
|
||
<div class="flex items-center justify-between mb-4">
|
||
<div class="w-12 h-12 bg-orange-100 rounded-xl flex items-center justify-center">
|
||
<ClockCircleOutlined class="text-orange-600 text-xl" />
|
||
</div>
|
||
<span class="text-red-500 text-sm font-medium flex items-center gap-1"><ArrowUpOutlined /> 5</span>
|
||
</div>
|
||
<h3 class="text-3xl font-bold text-gray-800 mb-1">12</h3>
|
||
<p class="text-gray-500 text-sm">待审批</p>
|
||
</div>
|
||
|
||
<div class="stat-card purple bg-white rounded-2xl p-6 card-hover shadow-sm">
|
||
<div class="flex items-center justify-between mb-4">
|
||
<div class="w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center">
|
||
<LineChartOutlined class="text-purple-600 text-xl" />
|
||
</div>
|
||
<span class="text-green-500 text-sm font-medium flex items-center gap-1"><ArrowUpOutlined /> 15%</span>
|
||
</div>
|
||
<h3 class="text-3xl font-bold text-gray-800 mb-1">¥89.5<span class="text-lg">万</span></h3>
|
||
<p class="text-gray-500 text-sm">本月支出</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 中间区域 -->
|
||
<div class="grid grid-cols-3 gap-6 mb-8">
|
||
<!-- 快捷入口 -->
|
||
<div class="bg-white rounded-2xl p-6 card-hover shadow-sm">
|
||
<h3 class="font-bold text-lg text-gray-800 mb-4 flex items-center gap-2">
|
||
<BoltOutlined class="text-yellow-500" />
|
||
快捷入口
|
||
</h3>
|
||
<div class="grid grid-cols-2 gap-3">
|
||
<button
|
||
v-for="shortcut in shortcuts"
|
||
:key="shortcut.label"
|
||
class="quick-btn flex items-center gap-2 px-4 py-3 bg-gray-50 rounded-xl text-gray-700 text-sm font-medium hover:bg-purple-500 hover:text-white transition-all"
|
||
>
|
||
<component :is="shortcut.icon" :style="{ color: shortcut.color }" />
|
||
{{ shortcut.label }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 待办事项 -->
|
||
<div class="bg-white rounded-2xl p-6 card-hover shadow-sm col-span-2">
|
||
<div class="flex items-center justify-between mb-4">
|
||
<h3 class="font-bold text-lg text-gray-800 flex items-center gap-2">
|
||
<CheckSquareOutlined class="text-red-500" />
|
||
待办事项
|
||
<span class="bg-red-100 text-red-600 px-2 py-0.5 rounded-full text-xs font-medium">5</span>
|
||
</h3>
|
||
<button class="text-purple-600 text-sm font-medium hover:underline">查看全部</button>
|
||
</div>
|
||
<div class="space-y-3">
|
||
<div
|
||
v-for="todo in todos"
|
||
:key="todo.id"
|
||
class="todo-item flex items-center gap-4 p-3 rounded-xl cursor-pointer hover:bg-purple-50 transition-all"
|
||
>
|
||
<div :class="['w-10 h-10 rounded-xl flex items-center justify-center flex-shrink-0', todo.bgColor]">
|
||
<component :is="todo.icon" :class="[todo.textColor]" />
|
||
</div>
|
||
<div class="flex-1">
|
||
<p class="font-medium text-gray-800">{{ todo.title }}</p>
|
||
<p class="text-xs text-gray-500">{{ todo.subtitle }}</p>
|
||
</div>
|
||
<span :class="['text-xs font-medium', todo.timeColor]">{{ todo.time }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 应用模块 -->
|
||
<div class="mb-8">
|
||
<div class="flex items-center justify-between mb-6">
|
||
<h3 class="font-bold text-xl text-gray-800">
|
||
<AppstoreOutlined class="text-purple-500 mr-2" />
|
||
应用模块
|
||
</h3>
|
||
<button class="text-purple-600 text-sm font-medium hover:underline">自定义模块</button>
|
||
</div>
|
||
<div class="grid grid-cols-6 gap-4">
|
||
<div
|
||
v-for="app in apps"
|
||
:key="app.name"
|
||
class="app-card bg-white rounded-2xl p-6 flex flex-col items-center justify-center card-hover cursor-pointer shadow-sm"
|
||
@click="navigateToApp(app.route)"
|
||
>
|
||
<div
|
||
class="app-icon w-16 h-16 rounded-2xl flex items-center justify-center mb-4 shadow-lg"
|
||
:style="{ background: app.gradient }"
|
||
>
|
||
<component :is="app.icon" class="text-white text-2xl" />
|
||
</div>
|
||
<h4 class="font-semibold text-gray-800 mb-1">{{ app.name }}</h4>
|
||
<p class="text-xs text-gray-500">{{ app.stats }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 底部区域 -->
|
||
<div class="grid grid-cols-2 gap-6">
|
||
<!-- 经营概览图表 -->
|
||
<div class="bg-white rounded-2xl p-6 card-hover shadow-sm">
|
||
<div class="flex items-center justify-between mb-6">
|
||
<h3 class="font-bold text-lg text-gray-800 flex items-center gap-2">
|
||
<BarChartOutlined class="text-blue-500" />
|
||
经营概览
|
||
</h3>
|
||
<div class="flex gap-2">
|
||
<button
|
||
v-for="period in ['本周', '本月', '本季']"
|
||
:key="period"
|
||
:class="['px-3 py-1 text-xs rounded-lg font-medium', activePeriod === period ? 'bg-purple-100 text-purple-600' : 'bg-gray-100 text-gray-600']"
|
||
@click="activePeriod = period"
|
||
>
|
||
{{ period }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="h-48 flex items-end gap-4">
|
||
<div
|
||
v-for="(bar, index) in chartData"
|
||
:key="index"
|
||
class="flex-1 flex flex-col items-center"
|
||
>
|
||
<div
|
||
class="w-full bg-gradient-to-t from-purple-500 to-purple-300 rounded-t-lg transition-all hover:opacity-80 cursor-pointer"
|
||
:style="{ height: bar + '%' }"
|
||
></div>
|
||
<span class="text-xs text-gray-500 mt-2">{{ weekDays[index] }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 最新公告 -->
|
||
<div class="bg-white rounded-2xl p-6 card-hover shadow-sm">
|
||
<div class="flex items-center justify-between mb-6">
|
||
<h3 class="font-bold text-lg text-gray-800 flex items-center gap-2">
|
||
<SoundOutlined class="text-red-500" />
|
||
最新公告
|
||
</h3>
|
||
<button class="text-purple-600 text-sm font-medium hover:underline">全部公告</button>
|
||
</div>
|
||
<div class="space-y-4">
|
||
<div
|
||
v-for="notice in notices"
|
||
:key="notice.id"
|
||
:class="['p-4 rounded-xl border-l-4 cursor-pointer hover:scale-[1.02] transition-transform', notice.bgColor, notice.borderColor]"
|
||
>
|
||
<h4 class="font-medium text-gray-800 mb-1">{{ notice.title }}</h4>
|
||
<div class="flex items-center gap-4 text-xs text-gray-500">
|
||
<span><UserOutlined class="mr-1" />{{ notice.author }}</span>
|
||
<span><ClockCircleOutlined class="mr-1" />{{ notice.date }}</span>
|
||
<span><EyeOutlined class="mr-1" />{{ notice.views }} 阅读</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, computed, h } from 'vue'
|
||
import {
|
||
HomeOutlined,
|
||
SettingOutlined,
|
||
ShoppingCartOutlined,
|
||
InboxOutlined,
|
||
WalletOutlined,
|
||
TeamOutlined,
|
||
ProjectOutlined,
|
||
UserOutlined,
|
||
LogoutOutlined,
|
||
ExpandOutlined,
|
||
BellOutlined,
|
||
GlobalOutlined,
|
||
ArrowUpOutlined,
|
||
CheckSquareOutlined,
|
||
BoltOutlined,
|
||
AppstoreOutlined,
|
||
BarChartOutlined,
|
||
SoundOutlined,
|
||
EyeOutlined,
|
||
ClockCircleOutlined,
|
||
LineChartOutlined,
|
||
SearchOutlined,
|
||
ShoppingOutlined,
|
||
TruckOutlined,
|
||
CalendarOutlined,
|
||
DollarOutlined,
|
||
BoxPlotOutlined,
|
||
ToolOutlined,
|
||
AuditOutlined,
|
||
ExperimentOutlined,
|
||
FileTextOutlined,
|
||
} from '@ant-design/icons-vue'
|
||
|
||
// 响应式数据
|
||
const searchQuery = ref('')
|
||
const activeMenu = ref('home')
|
||
const activePeriod = ref('本周')
|
||
|
||
// 当前日期
|
||
const currentDate = computed(() => {
|
||
const now = new Date()
|
||
return `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日 星期${['日', '一', '二', '三', '四', '五', '六'][now.getDay()]}`
|
||
})
|
||
|
||
// 剩余工作日
|
||
const remainingDays = computed(() => {
|
||
const now = new Date()
|
||
const day = now.getDay()
|
||
if (day === 0 || day === 6) return 0
|
||
return 5 - day
|
||
})
|
||
|
||
// 快捷入口
|
||
const shortcuts = [
|
||
{ label: '设备巡检', icon: SearchOutlined, color: '#667eea' },
|
||
{ label: '采购申请', icon: ShoppingOutlined, color: '#11998e' },
|
||
{ label: '入库登记', icon: TruckOutlined, color: '#f5576c' },
|
||
{ label: '请假申请', icon: CalendarOutlined, color: '#fc8181' },
|
||
{ label: '费用报销', icon: DollarOutlined, color: '#f6ad55' },
|
||
{ label: '库存查询', icon: BoxPlotOutlined, color: '#63b3ed' },
|
||
]
|
||
|
||
// 待办事项
|
||
const todos = [
|
||
{ id: 1, title: '审批 - 张三的报销单', subtitle: '差旅费 ¥2,580.00', time: '2小时前', icon: CheckSquareOutlined, bgColor: 'bg-red-100', textColor: 'text-red-600', timeColor: 'text-red-500' },
|
||
{ id: 2, title: '巡检 - 3号车间设备待检', subtitle: '包含12台设备', time: '4小时前', icon: SearchOutlined, bgColor: 'bg-yellow-100', textColor: 'text-yellow-600', timeColor: 'text-yellow-600' },
|
||
{ id: 3, title: '采购 - 办公用品采购单', subtitle: '待审批', time: '1天前', icon: ShoppingCartOutlined, bgColor: 'bg-blue-100', textColor: 'text-blue-600', timeColor: 'text-blue-600' },
|
||
{ id: 4, title: '保养 - 空压机定期保养', subtitle: '例行保养', time: '2天前', icon: ToolOutlined, bgColor: 'bg-green-100', textColor: 'text-green-600', timeColor: 'text-green-600' },
|
||
]
|
||
|
||
// 应用模块
|
||
const apps = [
|
||
{ name: '设备管理', icon: SettingOutlined, gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', stats: '128 设备', route: '/admin/device' },
|
||
{ name: '采购管理', icon: ShoppingCartOutlined, gradient: 'linear-gradient(135deg, #11998e 0%, #38ef7d 100%)', stats: '23 订单', route: '/admin/purchase' },
|
||
{ name: '仓储物流', icon: InboxOutlined, gradient: 'linear-gradient(135deg, #f5576c 0%, #f093fb 100%)', stats: '5,230 物料', route: '/admin/warehouse' },
|
||
{ name: '财务管理', icon: WalletOutlined, gradient: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)', stats: '¥89.5万', route: '/admin/finance' },
|
||
{ name: '人力资源', icon: TeamOutlined, gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', stats: '56 员工', route: '/admin/hr' },
|
||
{ name: '协同办公', icon: ProjectOutlined, gradient: 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)', stats: '8 流程', route: '/admin/office' },
|
||
]
|
||
|
||
// 图表数据
|
||
const chartData = [60, 75, 45, 90, 85, 40, 30]
|
||
const weekDays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||
|
||
// 公告
|
||
const notices = [
|
||
{ id: 1, title: '关于清明节放假安排的通知', author: '人事行政部', date: '2026-04-01', views: '1,258', bgColor: 'bg-red-50', borderColor: 'border-red-500' },
|
||
{ id: 2, title: '2026年第一季度财报公告', author: '财务部', date: '2026-03-28', views: '986', bgColor: 'bg-blue-50', borderColor: 'border-blue-500' },
|
||
{ id: 3, title: '新版本系统功能更新说明', author: '技术部', date: '2026-03-25', views: '756', bgColor: 'bg-green-50', borderColor: 'border-green-500' },
|
||
]
|
||
|
||
// 方法
|
||
const toggleFullscreen = () => {
|
||
if (!document.fullscreenElement) {
|
||
document.documentElement.requestFullscreen()
|
||
} else {
|
||
document.exitFullscreen()
|
||
}
|
||
}
|
||
|
||
const navigateToApp = (route: string) => {
|
||
navigateTo(route)
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.sidebar {
|
||
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
|
||
}
|
||
|
||
.sidebar-item:hover,
|
||
.sidebar-item.active {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
.card-hover {
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
|
||
.card-hover:hover {
|
||
transform: translateY(-4px);
|
||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.app-card {
|
||
aspect-ratio: 1;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.app-card:hover {
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.app-card:hover .app-icon {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
.app-icon {
|
||
transition: transform 0.3s ease;
|
||
}
|
||
|
||
.notification-badge {
|
||
animation: pulse 2s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.7; }
|
||
}
|
||
|
||
.quick-btn {
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.quick-btn:hover {
|
||
transform: translateX(4px);
|
||
}
|
||
</style>
|