85 lines
2.1 KiB
Vue
85 lines
2.1 KiB
Vue
<script setup lang="ts">
|
|
import type {
|
|
CustomerAnalysisCompositionItemDto,
|
|
CustomerAnalysisSegmentCode,
|
|
} from '#/api/customer';
|
|
|
|
import { computed } from 'vue';
|
|
|
|
import {
|
|
formatInteger,
|
|
formatPercent,
|
|
resolveCompositionToneColor,
|
|
} from '../composables/customer-analysis-page/helpers';
|
|
|
|
interface Props {
|
|
items: CustomerAnalysisCompositionItemDto[];
|
|
totalCustomers: number;
|
|
}
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
const emit = defineEmits<{
|
|
(event: 'segment', segmentCode: CustomerAnalysisSegmentCode): void;
|
|
}>();
|
|
|
|
const donutStyle = computed(() => {
|
|
if (props.items.length === 0) {
|
|
return {
|
|
background: 'conic-gradient(#e5e7eb 0deg 360deg)',
|
|
};
|
|
}
|
|
|
|
let angle = 0;
|
|
const parts: string[] = [];
|
|
for (const item of props.items) {
|
|
const start = angle;
|
|
const delta = Math.max(0, Math.min(360, (item.percent / 100) * 360));
|
|
angle += delta;
|
|
const end = Math.min(360, angle);
|
|
parts.push(
|
|
`${resolveCompositionToneColor(item.tone)} ${start}deg ${end}deg`,
|
|
);
|
|
}
|
|
|
|
if (angle < 360) {
|
|
parts.push(`#e5e7eb ${angle}deg 360deg`);
|
|
}
|
|
|
|
return {
|
|
background: `conic-gradient(${parts.join(',')})`,
|
|
};
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="ca-card">
|
|
<div class="ca-card-title">新老客占比</div>
|
|
<div class="ca-donut-wrap">
|
|
<div class="ca-donut" :style="donutStyle">
|
|
<div class="ca-donut-hole">
|
|
<div class="num">{{ formatInteger(props.totalCustomers) }}</div>
|
|
<div class="lbl">总客户</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ca-legend">
|
|
<button
|
|
v-for="item in props.items"
|
|
:key="item.segmentCode"
|
|
class="ca-legend-item"
|
|
type="button"
|
|
@click="emit('segment', item.segmentCode)"
|
|
>
|
|
<span
|
|
class="ca-legend-dot"
|
|
:style="{ backgroundColor: resolveCompositionToneColor(item.tone) }"
|
|
></span>
|
|
<span class="ca-legend-label">{{ item.label }}</span>
|
|
<span class="ca-legend-value">{{ formatPercent(item.percent) }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|