@tailwind base;
@tailwind components;
@tailwind utilities;
/* 背景图居中 */
/* 背景图居中覆盖 - 支持自定义padding控制 */
.bg-flex-center {
@apply flex items-center justify-center bg-center bg-no-repeat bg-contain;
}
/* 自定义样式 */
.crud-container {
@apply max-w-7xl mx-auto p-6;
}
.crud-header {
@apply mb-6 flex justify-between items-center;
}
.crud-table {
@apply bg-white rounded-lg shadow-sm;
}
.crud-form {
@apply bg-white p-6 rounded-lg shadow-sm;
}
/*
九宫格(9-slice)图片边框 Utility
目标:
- 传入一张九宫格图片的 URL,保持4个角按上下左右的参数不拉伸
- 中间和4个角中间的区域拉伸
- 支持自定义重复模式、填充行为、边框扩展等高级选项
核心参数:
- 图片URL:--nine-src
- 切片参数:--nine-top/right/bottom/left(基于图片实际像素)
- 快速设置:--nine-all(一次性设置四个角相等)
- 重复模式:--nine-repeat(stretch/repeat/round/space)
- 填充控制:--nine-fill(1 填充/0 不填充)
- 边框扩展:--nine-outset(向外扩展距离)
- 边框宽度:--nine-width(边框图像宽度)
使用说明(Tailwind 原子类 + CSS 变量):
1) 在元素上添加基础类:`nine-slice`
2) 通过 Tailwind 任意值设置 CSS 变量:
- 设置图片 URL:`[--nine-src:url('/public/images/frame-9.png')]`
- 设置切片大小:`[--nine-top:10] [--nine-right:10] [--nine-bottom:10] [--nine-left:10]`
- 快速设置(四个角相等):`[--nine-all:15]`(等效于设置四个角都为15)
- 可选高级参数:
- 重复模式:`[--nine-repeat:repeat]`(默认 stretch)
- 向外扩展:`[--nine-outset:5]`(默认 0)
- 边框宽度:`[--nine-width:2]`(默认 1)
3) 填充控制:
- 默认:填充中心区域
- 添加 `nine-slice-no-fill` 类:不填充中心,露出背景
示例:
内容区域
快速设置 - 四个角都是15px
重复图案边框
不填充中心
关键点:
- 使用 CSS border-image 实现精确的9宫格切片
- 4个角保持不拉伸,边缘和中心区域可配置拉伸或重复
- 支持 fill/unfill 控制中心区域填充
- 兼容所有现代浏览器
*/
@layer utilities {
.H2 {
@apply text-2xl font-bold;
}
.H3 {
@apply text-xl font-bold;
}
.H4 {
@apply text-base font-light;
}
.frame1 {
@apply nine-slice [--nine-src:url('/public/images/Frame1.png')] [--nine-all:10] [--nine-fill:1];
}
.frame-border2 {
@apply absolute inset-0 nine-slice [--nine-src:url('/public/images/frame-border2.png')] [--nine-all:50] [--nine-fill:1];
}
/* 九宫格边框类 - 支持基础到高级功能 */
.nine-slice {
border-style: solid;
width: 100%;
height: 100%;
/* 边框厚度:基于独立的切片值或快速设置 */
border-width: calc(var(--nine-top, var(--nine-all, 24)) * 1px)
calc(var(--nine-right, var(--nine-all, 24)) * 1px)
calc(var(--nine-bottom, var(--nine-all, 24)) * 1px)
calc(var(--nine-left, var(--nine-all, 24)) * 1px);
/* 边框图像 */
border-image-source: var(--nine-src);
/* 边框图像宽度 */
border-image-width: var(--nine-width, 1);
/* 边框图像向外扩展 */
border-image-outset: calc(var(--nine-outset, 0) * 1px);
/* 重复模式 - 支持 stretch, repeat, round, space */
border-image-repeat: var(--nine-repeat, stretch);
/* 默认切片设置(填充中心) */
border-image-slice: var(--nine-top, var(--nine-all, 24)) var(--nine-right, var(--nine-all, 24))
var(--nine-bottom, var(--nine-all, 24)) var(--nine-left, var(--nine-all, 24)) fill;
}
/* 不填充中心的变体 */
.nine-slice.nine-slice-no-fill {
border-image-slice: var(--nine-top, var(--nine-all, 24)) var(--nine-right, var(--nine-all, 24))
var(--nine-bottom, var(--nine-all, 24)) var(--nine-left, var(--nine-all, 24));
}
/* 动画支持 - 平滑过渡 */
.nine-slice-animated {
transition:
border-image-source 0.3s ease,
border-width 0.3s ease,
border-image-slice 0.3s ease;
}
}
/*
大屏看板专用 TailwindCSS Utilities
设计目标:
- 适配4K大屏分辨率 (3840x2160)
- 支持多种布局模式(网格、弹性、绝对定位)
- 提供专业的数据可视化容器
- 优化文字可读性和对比度
- 支持动态主题切换
*/
@layer utilities {
/* 大屏布局容器 */
.dashboard-container {
@apply w-full h-screen overflow-hidden bg-slate-900 text-white;
}
.dashboard-grid {
@apply grid gap-4 p-6 h-full;
}
.dashboard-grid-2x2 {
@apply grid grid-cols-2 grid-rows-2 gap-6 p-8;
}
.dashboard-grid-3x3 {
@apply grid grid-cols-3 grid-rows-3 gap-4 p-6;
}
.dashboard-grid-4x4 {
@apply grid grid-cols-4 grid-rows-4 gap-3 p-4;
}
/* 大屏卡片容器 */
.dashboard-card {
@apply bg-slate-800/80 backdrop-blur-sm rounded-xl border border-slate-700 p-6 shadow-2xl;
}
.dashboard-card-highlight {
@apply dashboard-card border-blue-500/50 bg-slate-800/90;
}
.dashboard-card-warning {
@apply dashboard-card border-amber-500/50 bg-orange-900/20;
}
.dashboard-card-danger {
@apply dashboard-card border-red-500/50 bg-red-900/20;
}
/* 大屏标题文字 */
.dashboard-title {
@apply text-4xl font-bold text-white tracking-wide mb-4;
}
.dashboard-subtitle {
@apply text-2xl font-semibold text-slate-300 mb-3;
}
.dashboard-metric-title {
@apply text-lg font-medium text-slate-400 mb-2;
}
/* 大屏数值显示 */
.dashboard-metric-large {
@apply text-6xl font-bold text-white tabular-nums;
}
.dashboard-metric-medium {
@apply text-5xl font-semibold text-white tabular-nums;
}
.dashboard-metric-small {
@apply text-3xl font-medium text-slate-200 tabular-nums;
}
.dashboard-metric-trend-up {
@apply text-green-400 text-2xl font-semibold;
}
.dashboard-metric-trend-down {
@apply text-red-400 text-2xl font-semibold;
}
/* 图表容器 */
.chart-container {
@apply w-full h-80 bg-slate-800/50 rounded-lg p-4 border border-slate-700;
}
.chart-container-large {
@apply w-full h-96 bg-slate-800/50 rounded-lg p-4 border border-slate-700;
}
.chart-container-small {
@apply w-full h-48 bg-slate-800/50 rounded-lg p-3 border border-slate-700;
}
/* 进度条 */
.dashboard-progress {
@apply w-full h-3 bg-slate-700 rounded-full overflow-hidden;
}
.dashboard-progress-bar {
@apply h-full bg-gradient-to-r from-blue-500 to-cyan-400 rounded-full transition-all duration-500;
}
.dashboard-progress-bar-success {
@apply bg-gradient-to-r from-green-500 to-emerald-400;
}
.dashboard-progress-bar-warning {
@apply bg-gradient-to-r from-amber-500 to-yellow-400;
}
.dashboard-progress-bar-danger {
@apply bg-gradient-to-r from-red-500 to-rose-400;
}
/* 状态指示器 */
.status-indicator {
@apply inline-flex items-center px-3 py-1 rounded-full text-sm font-medium;
}
.status-online {
@apply status-indicator bg-green-500/20 text-green-300 border border-green-500/30;
}
.status-offline {
@apply status-indicator bg-red-500/20 text-red-300 border border-red-500/30;
}
.status-warning {
@apply status-indicator bg-amber-500/20 text-amber-300 border border-amber-500/30;
}
.status-dot {
@apply w-3 h-3 rounded-full mr-2;
}
.status-dot-online {
@apply status-dot bg-green-400 animate-pulse;
}
.status-dot-offline {
@apply status-dot bg-red-400;
}
.status-dot-warning {
@apply status-dot bg-amber-400;
}
/* 动画效果 */
.dashboard-fade-in {
@apply animate-fade-in duration-1000;
}
.dashboard-slide-up {
@apply animate-slide-up duration-700;
}
.dashboard-scale-in {
@apply animate-scale-in duration-500;
}
/* 自定义动画 */
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes scale-in {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
.animate-fade-in {
animation: fade-in ease-out;
}
.animate-slide-up {
animation: slide-up ease-out;
}
.animate-scale-in {
animation: scale-in ease-out;
}
/* 数据表格样式 */
.dashboard-table {
@apply w-full border-collapse bg-slate-800/50 rounded-lg overflow-hidden;
}
.dashboard-table th {
@apply px-6 py-4 text-left text-sm font-semibold text-slate-300 border-b border-slate-700 bg-slate-800/80;
}
.dashboard-table td {
@apply px-6 py-4 text-sm text-slate-200 border-b border-slate-700/50;
}
.dashboard-table tr:hover {
@apply bg-slate-700/30;
}
/* 滚动条样式 */
.dashboard-scrollbar {
overflow: auto;
scrollbar-width: thin;
scrollbar-color: #475569 #1e293b;
}
.dashboard-scrollbar::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.dashboard-scrollbar::-webkit-scrollbar-track {
background: #1e293b;
border-radius: 4px;
}
.dashboard-scrollbar::-webkit-scrollbar-thumb {
background: #475569;
border-radius: 4px;
}
.dashboard-scrollbar::-webkit-scrollbar-thumb:hover {
background: #64748b;
}
/* 全屏模式 */
.dashboard-fullscreen {
@apply fixed inset-0 z-50 bg-slate-900;
}
/* 分屏布局 */
.dashboard-split-horizontal {
@apply grid grid-cols-2 gap-0 h-full;
}
.dashboard-split-vertical {
@apply grid grid-rows-2 gap-0 h-full;
}
/* 边缘对齐 */
.dashboard-align-top {
@apply flex items-start justify-center;
}
.dashboard-align-bottom {
@apply flex items-end justify-center;
}
.dashboard-align-left {
@apply flex items-center justify-start;
}
.dashboard-align-right {
@apply flex items-center justify-end;
}
/* 页面过渡动画 - 淡入淡出效果 */
.page-transition {
@apply transition-all duration-1000 ease-out;
}
.page-enter {
@apply opacity-0 scale-95;
}
.page-enter-active {
@apply transition-all duration-1000 ease-out;
}
.page-enter-to {
@apply opacity-100 scale-100;
}
.page-leave {
@apply opacity-100 scale-100;
}
.page-leave-active {
@apply transition-all duration-500 ease-in;
}
.page-leave-to {
@apply opacity-0 scale-95;
}
/* 元素淡入动画 */
.fade-in {
animation: fade-in 1s ease-out forwards;
opacity: 0; /* 初始状态设为透明,避免闪烁 */
}
.fade-in-left {
animation: fade-in-left 1s ease-out forwards;
opacity: 0; /* 初始状态设为透明,避免闪烁 */
}
.fade-in-right {
animation: fade-in-right 1s ease-out forwards;
opacity: 0; /* 初始状态设为透明,避免闪烁 */
}
.fade-in-up {
animation: fade-in-up 1s ease-out forwards;
}
.fade-in-down {
animation: fade-in-down 1s ease-out forwards;
}
/* 淡入动画关键帧 */
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-in-left {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fade-in-right {
from {
opacity: 0;
transform: translateX(20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fade-in-down {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 动画延迟工具类 */
.delay-100 {
animation-delay: 100ms;
}
.delay-200 {
animation-delay: 200ms;
}
.delay-300 {
animation-delay: 300ms;
}
.delay-400 {
animation-delay: 400ms;
}
.delay-500 {
animation-delay: 500ms;
}
.delay-600 {
animation-delay: 600ms;
}
.delay-700 {
animation-delay: 700ms;
}
.delay-800 {
animation-delay: 800ms;
}
.delay-900 {
animation-delay: 900ms;
}
.delay-1000 {
animation-delay: 1000ms;
}
}