style: 优化数据分析页面 UI

- 表格:移除边框,使用悬浮效果,表头透明化,优化内边距
- 徽章:使用 CSS 渐变色圆环代替 Emoji
- 卡片:移除描边,加深背景,柔化阴影
- 排版:优化对齐方式,增强呼吸感
This commit is contained in:
Your Name 2026-01-04 09:36:27 +08:00
parent 55921af840
commit 2a91ffd908

View File

@ -566,41 +566,41 @@ const efficiencyTableData = computed(() => [
// 表格列定义
const userColumns = [
{ title: '排名', key: 'rank', width: 60 },
{ title: '排名', key: 'rank', width: 80, align: 'center' },
{ title: '用户名', dataIndex: 'userName', key: 'userName' },
{ title: '部门', dataIndex: 'deptName', key: 'deptName' },
{ title: '发起数', dataIndex: 'totalDemands', key: 'totalDemands', sorter: (a: any, b: any) => a.totalDemands - b.totalDemands },
{ title: '完成数', dataIndex: 'completedDemands', key: 'completedDemands' },
{ title: '总积分', dataIndex: 'totalScore', key: 'totalScore' },
{ title: '完成率', key: 'completionRate', width: 150 }
{ title: '发起数', dataIndex: 'totalDemands', key: 'totalDemands', sorter: (a: any, b: any) => a.totalDemands - b.totalDemands, align: 'center' },
{ title: '完成数', dataIndex: 'completedDemands', key: 'completedDemands', align: 'center' },
{ title: '总积分', dataIndex: 'totalScore', key: 'totalScore', align: 'center' },
{ title: '完成率', key: 'completionRate', width: 150, align: 'center' }
]
const designerColumns = [
{ title: '排名', key: 'rank', width: 60 },
{ title: '排名', key: 'rank', width: 80, align: 'center' },
{ title: '设计师', dataIndex: 'realName', key: 'realName' },
{ title: '部门', dataIndex: 'deptName', key: 'deptName' },
{ title: '接单量', dataIndex: 'receivedCount', key: 'receivedCount', sorter: (a: any, b: any) => a.receivedCount - b.receivedCount },
{ title: '完成量', dataIndex: 'completedCount', key: 'completedCount' },
{ title: '完成率', dataIndex: 'completionRate', key: 'completionRate', customRender: ({ text }: any) => text + '%' },
{ title: '准时率', key: 'onTimeRate' },
{ title: '评分', key: 'avgRating', width: 140 }
{ title: '接单量', dataIndex: 'receivedCount', key: 'receivedCount', sorter: (a: any, b: any) => a.receivedCount - b.receivedCount, align: 'center' },
{ title: '完成量', dataIndex: 'completedCount', key: 'completedCount', align: 'center' },
{ title: '完成率', dataIndex: 'completionRate', key: 'completionRate', customRender: ({ text }: any) => text + '%', align: 'center' },
{ title: '准时率', key: 'onTimeRate', align: 'center' },
{ title: '评分', key: 'avgRating', width: 140, align: 'center' }
]
const efficiencyColumns = [
{ title: '指标', dataIndex: 'metric', key: 'metric' },
{ title: '本周', dataIndex: 'week', key: 'week' },
{ title: '上周', dataIndex: 'lastWeek', key: 'lastWeek' },
{ title: '环比', key: 'change' },
{ title: '本月', dataIndex: 'month', key: 'month' },
{ title: '目标', dataIndex: 'target', key: 'target' }
{ title: '本周', dataIndex: 'week', key: 'week', align: 'right' },
{ title: '上周', dataIndex: 'lastWeek', key: 'lastWeek', align: 'right' },
{ title: '环比', key: 'change', align: 'right' },
{ title: '本月', dataIndex: 'month', key: 'month', align: 'right' },
{ title: '目标', dataIndex: 'target', key: 'target', align: 'right' }
]
const warningColumns = [
{ title: '级别', key: 'level', width: 80 },
{ title: '级别', key: 'level', width: 100, align: 'center' },
{ title: '任务名称', dataIndex: 'taskTitle', key: 'taskTitle', ellipsis: true },
{ title: '处理人', dataIndex: 'receiverName', key: 'receiverName' },
{ title: '处理人', dataIndex: 'receiverName', key: 'receiverName', align: 'center' },
{ title: '预警原因', dataIndex: 'warningReason', key: 'warningReason' },
{ title: '操作', key: 'action', width: 140 }
{ title: '操作', key: 'action', width: 140, align: 'center' }
]
// 方法
@ -867,16 +867,18 @@ onMounted(() => {
.stat-card {
background: $bg-card;
border: 1px solid $border-primary;
border-radius: $radius-lg;
padding: $space-md;
padding: $space-lg;
display: flex;
gap: $space-md;
transition: all $transition-base $ease-out;
border: 1px solid rgba(255, 255, 255, 0.03);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
&:hover {
border-color: $brand-primary;
box-shadow: $shadow-base;
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
border-color: rgba($brand-primary, 0.3);
}
.stat-icon {
@ -886,6 +888,8 @@ onMounted(() => {
align-items: center;
justify-content: center;
flex-shrink: 0;
background: rgba($brand-primary, 0.1);
border-radius: 12px;
}
.stat-content {
@ -895,35 +899,41 @@ onMounted(() => {
.stat-label {
font-size: $font-size-sm;
color: $text-secondary;
margin-bottom: 4px;
margin-bottom: 8px;
}
.stat-value {
font-size: $font-size-xl;
font-weight: $font-weight-bold;
font-size: 28px;
font-weight: 700;
color: $text-primary;
line-height: 1;
}
}
}
.tabs-section {
:deep(.ant-tabs-nav) {
margin-bottom: $space-lg;
margin-bottom: $space-xl;
.ant-tabs-tab {
color: $text-secondary;
padding: 12px 0;
transition: all 0.3s;
&:hover {
color: $brand-primary;
color: $text-primary;
}
&.ant-tabs-tab-active .ant-tabs-tab-btn {
color: $brand-primary;
font-weight: 600;
}
}
.ant-tabs-ink-bar {
background: $brand-primary;
height: 3px;
border-radius: 3px;
}
}
}
@ -934,42 +944,53 @@ onMounted(() => {
.chart-card, .table-card {
background: $bg-card;
border: 1px solid $border-primary;
border-radius: $radius-lg;
padding: $space-lg;
padding: $space-xl;
border: 1px solid rgba(255, 255, 255, 0.03);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
margin-bottom: 24px;
.chart-title {
font-size: $font-size-base;
font-weight: $font-weight-semibold;
font-size: $font-size-lg;
font-weight: 600;
color: $text-primary;
margin-bottom: $space-md;
margin-bottom: $space-lg;
display: flex;
align-items: center;
gap: 8px;
.count-badge {
font-size: $font-size-sm;
font-weight: normal;
color: $text-secondary;
background: rgba(255, 255, 255, 0.05);
padding: 2px 8px;
border-radius: 10px;
}
}
}
.mini-stat-card {
background: $bg-tertiary;
background: $bg-card;
border-radius: $radius-md;
padding: $space-md;
padding: $space-lg;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.03);
&.warning {
border: 1px solid $color-warning;
border: 1px solid rgba($color-warning, 0.3);
background: rgba($color-warning, 0.05);
}
.mini-stat-label {
font-size: $font-size-sm;
color: $text-secondary;
margin-bottom: 4px;
margin-bottom: 8px;
}
.mini-stat-value {
font-size: $font-size-xl;
font-weight: $font-weight-bold;
font-size: 24px;
font-weight: 700;
color: $text-primary;
}
}
@ -978,27 +999,34 @@ onMounted(() => {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
width: 24px;
height: 24px;
border-radius: 50%;
font-weight: $font-weight-bold;
font-size: $font-size-sm;
background: $bg-tertiary;
font-weight: 700;
font-size: 12px;
background: rgba(255, 255, 255, 0.05);
color: $text-secondary;
border: 1px solid rgba(255, 255, 255, 0.1);
&.rank-1 {
background: rgba(#FFD700, 0.2);
color: #FFD700;
background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
color: #fff;
border: none;
box-shadow: 0 2px 4px rgba(255, 215, 0, 0.3);
}
&.rank-2 {
background: rgba(#C0C0C0, 0.2);
color: #C0C0C0;
background: linear-gradient(135deg, #E0E0E0 0%, #A0A0A0 100%);
color: #fff;
border: none;
box-shadow: 0 2px 4px rgba(192, 192, 192, 0.3);
}
&.rank-3 {
background: rgba(#CD7F32, 0.2);
color: #CD7F32;
background: linear-gradient(135deg, #CD7F32 0%, #8B4513 100%);
color: #fff;
border: none;
box-shadow: 0 2px 4px rgba(205, 127, 50, 0.3);
}
}
@ -1009,9 +1037,9 @@ onMounted(() => {
// 流程图样式
.process-flow-card {
background: $bg-card;
border: 1px solid $border-primary;
border-radius: $radius-lg;
padding: $space-xl;
border: 1px solid rgba(255, 255, 255, 0.03);
}
.process-flow {
@ -1019,39 +1047,50 @@ onMounted(() => {
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: $space-sm;
margin: $space-xl 0;
gap: $space-lg;
margin: 40px 0;
}
.process-step {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
gap: 8px;
position: relative;
.step-name {
font-size: $font-size-sm;
color: $text-primary;
padding: $space-sm $space-md;
background: $bg-tertiary;
border-radius: $radius-md;
padding: 8px 16px;
background: rgba(255, 255, 255, 0.05);
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.step-time {
font-size: $font-size-xs;
font-size: 13px;
color: $brand-primary;
font-weight: $font-weight-bold;
font-weight: 600;
}
.step-arrow {
color: $text-tertiary;
font-size: $font-size-lg;
color: rgba(255, 255, 255, 0.2);
font-size: 20px;
position: absolute;
right: -24px;
top: 50%;
transform: translateY(-50%);
}
&:last-child .step-arrow {
display: none;
}
&.bottleneck {
.step-name {
background: rgba($color-warning, 0.2);
border: 1px solid $color-warning;
background: rgba($color-warning, 0.1);
border-color: rgba($color-warning, 0.3);
color: $color-warning;
}
}
}
@ -1059,9 +1098,13 @@ onMounted(() => {
.process-summary {
text-align: center;
color: $text-secondary;
margin-top: $space-lg;
padding-top: $space-lg;
border-top: 1px solid rgba(255, 255, 255, 0.05);
strong {
color: $text-primary;
font-size: 16px;
}
.bottleneck-info {
@ -1072,76 +1115,110 @@ onMounted(() => {
// 预警卡片样式
.warning-stat-card {
background: $bg-tertiary;
border-radius: $radius-md;
background: $bg-card;
border-radius: $radius-lg;
padding: $space-lg;
text-align: center;
cursor: pointer;
transition: all $transition-base;
border: 1px solid rgba(255, 255, 255, 0.03);
position: relative;
overflow: hidden;
&:hover {
transform: translateY(-2px);
box-shadow: $shadow-base;
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2);
}
&.urgent { border: 1px solid $color-error; }
&.warning { border: 1px solid $color-warning; }
&.normal { border: 1px solid $color-success; }
&.all { border: 1px solid $brand-primary; }
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
}
&.urgent::before { background: $color-error; }
&.warning::before { background: $color-warning; }
&.normal::before { background: $color-success; }
&.all::before { background: $brand-primary; }
.warning-icon {
font-size: 24px;
margin-bottom: $space-xs;
font-size: 28px;
margin-bottom: 12px;
opacity: 0.8;
}
.warning-label {
font-size: $font-size-sm;
color: $text-secondary;
margin-bottom: 4px;
}
.warning-count {
font-size: $font-size-2xl;
font-weight: $font-weight-bold;
font-size: 32px;
font-weight: 700;
color: $text-primary;
}
}
.level-badge {
padding: 2px 8px;
border-radius: $radius-sm;
font-size: $font-size-xs;
padding: 4px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
&.urgent {
background: rgba($color-error, 0.1);
color: $color-error;
background: rgba($color-error, 0.15);
color: lighten($color-error, 10%);
border: 1px solid rgba($color-error, 0.2);
}
&.warning {
background: rgba($color-warning, 0.1);
color: $color-warning;
background: rgba($color-warning, 0.15);
color: lighten($color-warning, 10%);
border: 1px solid rgba($color-warning, 0.2);
}
}
// Ant Design 深色主题覆盖
:deep(.ant-table) {
background: transparent !important;
color: $text-primary;
.ant-table-thead > tr > th {
background: $bg-tertiary !important;
border-color: $border-color !important;
color: $text-primary !important;
// 移除边框
.ant-table-container {
border: none !important;
}
.ant-table-tbody > tr {
&:hover > td {
background: $bg-tertiary !important;
}
.ant-table-thead > tr > th {
background: transparent !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.05) !important;
color: $text-secondary !important;
font-weight: 500;
padding: 16px;
> td {
border-color: $border-color !important;
color: $text-primary !important;
&::before {
display: none !important; // 移除表头分割线
}
}
.ant-table-tbody > tr > td {
border-bottom: 1px solid rgba(255, 255, 255, 0.02) !important;
padding: 16px;
color: $text-primary;
transition: background 0.3s;
}
.ant-table-tbody > tr:hover > td {
background: rgba(255, 255, 255, 0.03) !important;
}
// 移除所有垂直边框
.ant-table-cell {
border-right: none !important;
}
}
:deep(.ant-tabs) {
@ -1151,14 +1228,20 @@ onMounted(() => {
:deep(.ant-select) {
.ant-select-selector {
background: $bg-tertiary !important;
border-color: $border-color !important;
border-color: rgba(255, 255, 255, 0.1) !important;
color: $text-primary !important;
border-radius: 6px !important;
}
.ant-select-arrow {
color: $text-secondary !important;
}
}
:deep(.ant-picker) {
background: $bg-tertiary !important;
border-color: $border-color !important;
border-color: rgba(255, 255, 255, 0.1) !important;
border-radius: 6px !important;
.ant-picker-input > input {
color: $text-primary !important;
@ -1169,7 +1252,14 @@ onMounted(() => {
}
}
:deep(.ant-btn) {
border-radius: 6px;
}
:deep(.ant-rate) {
font-size: 14px;
color: rgba(255, 255, 255, 0.1);
.ant-rate-star-full .ant-rate-star-second {
color: #FFD700 !important;
}