Files
admin-web/src/modules/self-operated/components/DashboardBars.vue
T

55 lines
3.7 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import AppDialog from '@/shared/components/AppDialog.vue'
import type { ECElementEvent } from 'echarts'
import { quantityText } from '../state'
import { barChartOption, type BarRow } from '../dashboardChartOptions'
import AnalyticsChart from './AnalyticsChart.vue'
import DashboardChartHeading from './DashboardChartHeading.vue'
export type { BarRow } from '../dashboardChartOptions'
const props = defineProps<{ rows: BarRow[]; unit: string; disabled?: boolean; title: string; ranked?: boolean; detailsWidth?: string }>()
const emit = defineEmits<{ select: [key: string] }>()
const option = computed(() => barChartOption(props.rows, props.unit, props.title, props.ranked))
const detailsOpen = ref(false)
watch(() => props.rows, () => { detailsOpen.value = false })
function select(row: BarRow) { if (!props.disabled && row.value != null) { detailsOpen.value = false; emit('select', row.key) } }
function selectChart(event: ECElementEvent) {
const row = event.componentType === 'yAxis' ? props.rows.find(row => row.key === String(event.value)) : event.componentType === 'series' ? props.rows[event.dataIndex] : undefined
if (row) select(row)
}
</script>
<template>
<div :aria-label="title" class="dashboard-bars">
<DashboardChartHeading :title="title">
<span v-if="rows.length" class="chart-details-action"><el-button link type="primary" title="查看完整明细" @click="detailsOpen = true">明细</el-button></span>
<slot name="actions" />
</DashboardChartHeading>
<slot name="intro" />
<slot v-if="!rows.length" name="empty"><p>暂无符合条件的 SKU;请核对覆盖与待评估资料。</p></slot>
<template v-else>
<AnalyticsChart :option="option" :style="{ height: `${Math.max(240, rows.length * 38 + 65)}px` }" :aria-label="title" @select="selectChart" />
<p v-if="rows.some(row => row.value == null)">存在待核验数量,以“—”表示,不作为零值。</p>
<AppDialog v-model="detailsOpen" class="admin-density-dialog" :title="`${title} · 完整明细`" :width="detailsWidth || '1040px'" :show-confirm="false" cancel-text="关闭" fullscreenable append-to-body destroy-on-close>
<div class="admin-density chart-details">
<slot name="details" :select="select">
<p>当前图表共 {{ rows.length }} 项;点击项目查看对应明细。</p>
<table class="density-table"><thead><tr><th v-if="ranked" class="rank-column">排名</th><th class="name-column">项目/完整名称</th><th class="quantity-column">数量({{ unit }})</th><th>说明</th></tr></thead><tbody><tr v-for="(row, index) in rows" :key="row.key"><td v-if="ranked">{{ index + 1 }}</td><td><button type="button" :disabled="disabled || row.value == null" @click="select(row)">{{ row.label }}</button><small v-if="row.secondary">{{ row.secondary }}</small></td><td>{{ quantityText(row.value) }}</td><td>{{ row.detail || '—' }}</td></tr></tbody></table>
</slot>
</div>
</AppDialog>
</template>
</div>
</template>
<style scoped>
.dashboard-bars { min-width: 0; }
small { display: block; color: var(--el-text-color-secondary); font-size: var(--admin-font-caption); }
td { overflow-wrap: anywhere; vertical-align: top; }
.chart-details-action { display: inline-flex; }
.chart-details table { width: 100%; table-layout: fixed; }
.rank-column { width: 56px; }
.name-column { width: 30%; }
.quantity-column { width: 120px; }
.chart-details button { font: inherit; color: var(--el-color-primary); background: transparent; border: 0; cursor: pointer; padding: var(--admin-space-2); }
.chart-details button:disabled { color: var(--el-text-color-secondary); cursor: default; }
</style>