4 changed files with 198 additions and 164 deletions
@ -1,180 +1,194 @@ |
|||||||
<template> |
<template> |
||||||
<div class="flex between v-center mb-10"> |
<div class="flex between v-center mb-10"> |
||||||
<span class="bar-title">{{ title }}</span> |
<span class="bar-title">{{ title }}</span> |
||||||
<span class="bar-sub-title">{{ subTitle }}</span> |
<span class="bar-sub-title">{{ subTitle }}</span> |
||||||
</div> |
</div> |
||||||
<div> |
<div> |
||||||
<div |
<div |
||||||
class="flex v-center bar-item wrap between " |
class="flex v-center bar-item wrap between " |
||||||
v-for="item in data" |
v-for="item in data" |
||||||
:size="size" |
:size="size" |
||||||
:style="{ '--label-width': `${labelWidth}px` }" |
:style="{ '--label-width': `${labelWidth}px` }" |
||||||
:position="labelPosition" |
:position="labelPosition" |
||||||
style="height: 40px" |
style="height: 40px" |
||||||
> |
> |
||||||
<span style="margin-left: 18px"> |
<span style="margin-left: 18px"> |
||||||
{{ item.sort }} |
{{ item.sort }} |
||||||
</span> |
</span> |
||||||
<div class="bar-item_content mr-8 " :long="!item.denominator" > |
<div class="bar-item_content mr-8 " :long="!item.denominator"> |
||||||
<span>{{item.label}}</span> |
<span>{{ item.label }}</span> |
||||||
<div |
<div |
||||||
class="bar-item_content-bar" |
class="bar-item_content-bar" |
||||||
:style="{ |
:style="{ |
||||||
width: `${(item.value / max) * 100}%`, |
width: `${(item.value / max) * 100}%`, |
||||||
background: getColor((item.value / max) * 100), |
background: getColor((item.value / max) * 100), |
||||||
}" |
}" |
||||||
></div> |
></div> |
||||||
</div> |
</div> |
||||||
<span >{{ item.value }}</span> |
<span>{{ item.value }}</span> |
||||||
<span |
<span |
||||||
class="bar-item_remark text-right ml-8" |
class="bar-item_remark text-right ml-8" |
||||||
v-if="item.denominator" |
v-if="item.denominator" |
||||||
style="min-width: 40px" |
style="min-width: 40px" |
||||||
> |
> |
||||||
<span class="text-success">{{ item.numerator }}</span> |
<span class="text-success">{{ item.numerator }}</span> |
||||||
<span>/</span> |
<span>/</span> |
||||||
<span>{{ item.denominator }}</span> |
<span>{{ item.denominator }}</span> |
||||||
</span> |
</span> |
||||||
</div> |
|
||||||
</div> |
</div> |
||||||
|
</div> |
||||||
</template> |
</template> |
||||||
<script setup> |
<script setup> |
||||||
import { onMounted } from "vue"; |
import {onMounted} from "vue"; |
||||||
|
|
||||||
const props = defineProps({ |
const props = defineProps({ |
||||||
title: { |
title: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
subTitle: { |
subTitle: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
data: { |
data: { |
||||||
type: Array, |
type: Array, |
||||||
default: [], |
default: [], |
||||||
}, |
}, |
||||||
size: { |
size: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
unit: { |
unit: { |
||||||
type: String, |
type: String, |
||||||
default: "", |
default: "", |
||||||
}, |
}, |
||||||
color: { |
color: { |
||||||
type: Object, |
type: Object, |
||||||
default: "linear-gradient(270deg, #63e700 0%, #19674c 100%)", |
default: "linear-gradient(270deg, #63e700 0%, #19674c 100%)", |
||||||
}, |
}, |
||||||
labelWidth: { |
labelWidth: { |
||||||
type: Number, |
type: Number, |
||||||
default: 60, |
default: 60, |
||||||
}, |
}, |
||||||
labelPosition: { |
labelPosition: { |
||||||
type: String, |
type: String, |
||||||
default: "left", |
default: "left", |
||||||
}, |
}, |
||||||
}); |
}); |
||||||
|
|
||||||
const max = ref(100); |
const max = ref(100); |
||||||
watch( |
watch( |
||||||
() => props.data, |
() => props.data, |
||||||
() => { |
() => { |
||||||
getMax(); |
getMax(); |
||||||
} |
} |
||||||
); |
); |
||||||
|
|
||||||
function getMax() { |
function getMax() { |
||||||
if (props.unit !== "%") { |
if (props.unit !== "%") { |
||||||
max.value = Math.max(...props.data.map((item) => item.value)); |
max.value = Math.max(...props.data.map((item) => item.value)); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
onMounted(() => { |
onMounted ( () => { |
||||||
getMax(); |
getMax(); |
||||||
|
|
||||||
}); |
}); |
||||||
|
|
||||||
function getColor(val) { |
function getColor(val) { |
||||||
if (props.color instanceof String) { |
if (props.color instanceof String) { |
||||||
return props.color; |
return props.color; |
||||||
} |
} |
||||||
if (props.color instanceof Array) { |
if (props.color instanceof Array) { |
||||||
const colors = [...props.color]; |
const colors = [...props.color]; |
||||||
colors.sort((a, b) => b.percentage - a.percentage); |
colors.sort((a, b) => b.percentage - a.percentage); |
||||||
for (let i = 0; i < colors.length; i++) { |
for (let i = 0; i < colors.length; i++) { |
||||||
if (val > colors[0].percentage) { |
if (val > colors[0].percentage) { |
||||||
return colors[0].color; |
return colors[0].color; |
||||||
} |
} |
||||||
} |
|
||||||
} |
} |
||||||
return "linear-gradient(270deg, #63e700 0%, #19674c 100%)"; |
} |
||||||
// if (val >= 0.7) { |
return "linear-gradient(270deg, #63e700 0%, #19674c 100%)"; |
||||||
// return "linear-gradient( 270deg, #FFB90E 0%, #71501D 100%)"; |
// if (val >= 0.7) { |
||||||
// } |
// return "linear-gradient( 270deg, #FFB90E 0%, #71501D 100%)"; |
||||||
// return "linear-gradient( 270deg, #FB002D 0%, #822232 100%)"; |
// } |
||||||
|
// return "linear-gradient( 270deg, #FB002D 0%, #822232 100%)"; |
||||||
} |
} |
||||||
</script> |
</script> |
||||||
<style lang="scss" scoped> |
<style lang="scss" scoped> |
||||||
.bar-title { |
.bar-title { |
||||||
font-size: 19px; |
font-size: 19px; |
||||||
} |
} |
||||||
|
|
||||||
.bar-sub-title { |
.bar-sub-title { |
||||||
color: #597ae9; |
color: #597ae9; |
||||||
font-size: 14px; |
font-size: 14px; |
||||||
} |
} |
||||||
|
|
||||||
.bar-item { |
.bar-item { |
||||||
font-size: 17px; |
font-size: 17px; |
||||||
&[size="large"] { |
|
||||||
.bar-item_content { |
&[size="large"] { |
||||||
.bar-item_content-bar { |
.bar-item_content { |
||||||
height: 13px; |
.bar-item_content-bar { |
||||||
} |
height: 13px; |
||||||
} |
} |
||||||
} |
|
||||||
&[size="small"] { |
|
||||||
font-size: 12px; |
|
||||||
} |
} |
||||||
|
} |
||||||
|
|
||||||
|
&[size="small"] { |
||||||
|
font-size: 12px; |
||||||
|
} |
||||||
|
|
||||||
|
.bar-item-label { |
||||||
|
text-align: right; |
||||||
|
width: var(--label-width); |
||||||
|
overflow: hidden; |
||||||
|
white-space: nowrap; |
||||||
|
text-overflow: ellipsis; |
||||||
|
} |
||||||
|
|
||||||
|
&[position="left"] { |
||||||
|
height: 32px; |
||||||
|
line-height: 32px; |
||||||
|
} |
||||||
|
|
||||||
|
&[position="top"] { |
||||||
|
margin-bottom: 4px; |
||||||
|
|
||||||
.bar-item-label { |
.bar-item-label { |
||||||
text-align: right; |
width: 100%; |
||||||
width: var(--label-width); |
text-align: left; |
||||||
overflow: hidden; |
|
||||||
white-space: nowrap; |
|
||||||
text-overflow: ellipsis; |
|
||||||
} |
} |
||||||
&[position="left"] { |
|
||||||
height: 32px; |
.bar-item_content { |
||||||
line-height: 32px; |
width: calc(100% - 80px); |
||||||
} |
} |
||||||
&[position="top"] { |
} |
||||||
margin-bottom: 4px; |
|
||||||
.bar-item-label { |
.bar-item_content { |
||||||
width: 100%; |
width: calc(100% - var(--label-width) - 16px - 30px); |
||||||
text-align: left; |
|
||||||
} |
&[long=false] { |
||||||
.bar-item_content { |
width: calc(100% - var(--label-width) - 36px - 58px); |
||||||
width: calc(100% - 80px); |
|
||||||
} |
|
||||||
} |
} |
||||||
.bar-item_content { |
|
||||||
width: calc(100% - var(--label-width) - 16px - 30px); |
.bar-item_content-bar { |
||||||
&[long=false] { |
width: 0; |
||||||
width: calc(100% - var(--label-width) - 36px - 58px); |
height: 9px; |
||||||
} |
background: linear-gradient(270deg, #63e700 0%, #19674c 100%); |
||||||
.bar-item_content-bar { |
transition: width 0.3s; |
||||||
width: 0; |
|
||||||
height: 9px; |
|
||||||
background: linear-gradient(270deg, #63e700 0%, #19674c 100%); |
|
||||||
transition: width 0.3s; |
|
||||||
} |
|
||||||
} |
} |
||||||
.bar-item_remark { |
} |
||||||
font-size: 14px; |
|
||||||
.text-success { |
.bar-item_remark { |
||||||
color: #09c700; |
font-size: 14px; |
||||||
} |
|
||||||
|
.text-success { |
||||||
|
color: #09c700; |
||||||
} |
} |
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style> |
</style> |
||||||
Loading…
Reference in new issue