feat: 概览页移除类目分布,检索按钮与输入框同高对齐
This commit is contained in:
@@ -9,7 +9,6 @@ import {
|
|||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
QuestionCircleOutlined,
|
QuestionCircleOutlined,
|
||||||
ReloadOutlined,
|
ReloadOutlined,
|
||||||
AppstoreOutlined,
|
|
||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
SettingOutlined
|
SettingOutlined
|
||||||
} from '@ant-design/icons-vue'
|
} from '@ant-design/icons-vue'
|
||||||
@@ -147,36 +146,6 @@ const cards = computed(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const categoryBars = computed(() => {
|
|
||||||
const categories = statsData.value?.categories || {}
|
|
||||||
const entries = Object.entries(categories).map(([name, count]) => ({ name, count }))
|
|
||||||
entries.sort((a, b) => b.count - a.count)
|
|
||||||
const max = entries.reduce((acc, item) => Math.max(acc, item.count), 1)
|
|
||||||
const total = entries.reduce((acc, item) => acc + item.count, 0)
|
|
||||||
return entries.map((item) => ({
|
|
||||||
...item,
|
|
||||||
percent: Math.round((item.count / max) * 100),
|
|
||||||
ratio: total ? Math.round((item.count / total) * 100) : 0
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
|
|
||||||
const gradientColors = [
|
|
||||||
'linear-gradient(90deg, #1677ff 0%, #4096ff 100%)',
|
|
||||||
'linear-gradient(90deg, #722ed1 0%, #9254de 100%)',
|
|
||||||
'linear-gradient(90deg, #13c2c2 0%, #36cfc9 100%)',
|
|
||||||
'linear-gradient(90deg, #fa8c16 0%, #ffa940 100%)',
|
|
||||||
'linear-gradient(90deg, #52c41a 0%, #73d13d 100%)',
|
|
||||||
'linear-gradient(90deg, #eb2f96 0%, #f759ab 100%)',
|
|
||||||
'linear-gradient(90deg, #fa541c 0%, #ff7a45 100%)',
|
|
||||||
'linear-gradient(90deg, #2f54eb 0%, #597ef7 100%)',
|
|
||||||
'linear-gradient(90deg, #08979c 0%, #13c2c2 100%)',
|
|
||||||
'linear-gradient(90deg, #c41d7f 0%, #eb2f96 100%)'
|
|
||||||
]
|
|
||||||
|
|
||||||
function barGradient(index) {
|
|
||||||
return gradientColors[index % gradientColors.length]
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadStats() {
|
async function loadStats() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
try {
|
try {
|
||||||
@@ -310,38 +279,6 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 类目分布 -->
|
|
||||||
<div class="overview__section">
|
|
||||||
<div class="overview__section-head">
|
|
||||||
<h3 class="overview__subtitle">
|
|
||||||
<AppstoreOutlined />
|
|
||||||
<span>类目分布</span>
|
|
||||||
</h3>
|
|
||||||
<span v-if="categoryBars.length" class="text-muted overview__section-meta">
|
|
||||||
共 {{ categoryBars.length }} 个类目
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div v-if="categoryBars.length === 0" class="overview__empty text-muted">暂无数据</div>
|
|
||||||
<div v-else class="overview__bars">
|
|
||||||
<div
|
|
||||||
v-for="(bar, idx) in categoryBars"
|
|
||||||
:key="bar.name"
|
|
||||||
class="overview__bar-row"
|
|
||||||
:title="`${bar.name}: ${bar.count} (${bar.ratio}%)`"
|
|
||||||
>
|
|
||||||
<span class="overview__bar-name" :title="bar.name">{{ bar.name }}</span>
|
|
||||||
<div class="overview__bar-track">
|
|
||||||
<div
|
|
||||||
class="overview__bar-fill"
|
|
||||||
:style="{ width: bar.percent + '%', background: barGradient(idx) }"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<span class="overview__bar-count">{{ bar.count }}</span>
|
|
||||||
<span class="overview__bar-ratio">{{ bar.ratio }}%</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 检索参数设置弹窗 -->
|
<!-- 检索参数设置弹窗 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:open="paramsVisible"
|
v-model:open="paramsVisible"
|
||||||
@@ -402,7 +339,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
.overview__search-bar {
|
.overview__search-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: stretch;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
max-width: 760px;
|
max-width: 760px;
|
||||||
@@ -412,14 +349,22 @@ onMounted(() => {
|
|||||||
.overview__search-form {
|
.overview__search-form {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview__search-form-item {
|
.overview__search-form-item {
|
||||||
|
flex: 1;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overview__search-form-item .ant-form-item-control {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.overview__search-input {
|
.overview__search-input {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview__search-params {
|
.overview__search-params {
|
||||||
@@ -489,94 +434,7 @@ onMounted(() => {
|
|||||||
color: #1f2937;
|
color: #1f2937;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview__section {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__section-head {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__subtitle {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #374151;
|
|
||||||
margin: 0 0 12px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__section-meta {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__empty {
|
|
||||||
text-align: center;
|
|
||||||
padding: 32px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__bars {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__bar-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 13px;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__bar-name {
|
|
||||||
width: 180px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: #374151;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__bar-track {
|
|
||||||
flex: 1;
|
|
||||||
background: #f3f4f6;
|
|
||||||
border-radius: 4px;
|
|
||||||
height: 18px;
|
|
||||||
margin: 0 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__bar-fill {
|
|
||||||
height: 100%;
|
|
||||||
border-radius: 4px;
|
|
||||||
min-width: 2px;
|
|
||||||
transition: width 0.4s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__bar-count {
|
|
||||||
width: 48px;
|
|
||||||
text-align: right;
|
|
||||||
color: #1f2937;
|
|
||||||
font-weight: 600;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview__bar-ratio {
|
|
||||||
width: 48px;
|
|
||||||
text-align: right;
|
|
||||||
color: #6b7280;
|
|
||||||
font-size: 12px;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.overview__bar-name {
|
|
||||||
width: 120px;
|
|
||||||
}
|
|
||||||
.overview__search-bar {
|
.overview__search-bar {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user