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

59 lines
4.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ChartNoAxesCombined } from '@lucide/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 workbench-chart">
<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" />
<div v-if="!rows.length" class="workbench-chart-empty" role="status">
<span class="workbench-chart-empty-icon" aria-hidden="true"><ChartNoAxesCombined :size="28" /></span>
<slot name="empty"><p>暂无符合条件的 SKU;请核对覆盖与待评估资料。</p></slot>
</div>
<template v-else>
<AnalyticsChart :option="option" class="workbench-chart-canvas" :style="{ height: `${Math.max(240, rows.length * 38 + 65)}px` }" :aria-label="title" @select="selectChart" />
<p v-if="rows.some(row => row.value == null)" class="workbench-note">存在待核验数量,以“—”表示,不作为零值。</p>
<AppDialog v-model="detailsOpen" class="admin-density-dialog admin-workbench is-dialog" :title="`${title} · 完整明细`" :width="detailsWidth || '1040px'" :show-confirm="false" cancel-text="关闭" fullscreenable append-to-body destroy-on-close>
<div class="admin-density chart-details workbench-evidence">
<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>