Files
yudao-dev/src/views/home/expenseAnalysisComponents/yearRelatedMetrics.vue

185 lines
5.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.

<template>
<div style="flex: 1">
<Container :name="title" icon="cockpitItemIcon" size="operatingRevenueBg" topSize="middle">
<div class="kpi-content" style="padding: 14px 16px; display: flex; width: 100%;">
<div class="topItem-container" style="display: flex; gap: 8px">
<div
v-for="item in sortedIndicators"
:key="item.key"
class="dashboard"
@click="item.route && handleDashboardClick(item.route)"
>
<div class="title">
{{ item.name }}·{{ item.unit }}
</div>
<div style='font-size: 14px;text-align: right;padding-right: 5px;'>
<span>完成率:<span style='color: #0B58FF;'>{{item.detailData.rate}}%</span></span>
<span style='display: inline-block;margin-left: 10px;'>差值:<span :style="{color:item.detailData.flag>0?'#30B590':'#FF9423'}" >{{item.detailData.diff}}</span></span>
</div>
<operatingSingleBar :detailData="item.detailData"></operatingSingleBar>
</div>
</div>
</div>
</Container>
</div>
</template>
<script>
import Container from './container.vue'
import operatingSingleBar from './operatingSingleBar.vue'
export default {
name: 'CostAnalysis', // 语义化组件名
components: { Container, operatingSingleBar },
props: {
// 费用数据:数组包含管理/销售/财务费用三个对象
ytdAnalysis: {
type: Array,
default: () => [
{ title: "管理费用", budget: 0, real: 0, rate: 0, diff: 0 },
{ title: "销售费用", budget: 0, real: 0, rate: 0, diff: 0 },
{ title: "财务费用", budget: 0, real: 0, rate: 0, diff: 0 }
]
},
title: {
type: String,
default: '费用分析'
},
month: {
type: String,
default: ''
},
},
data() {
return {
// 初始化费用数据包含flag字段
manageCostData: { title: "管理费用", budget: 0, real: 0, rate: 0, diff: 0, flag: 0 },
saleCostData: { title: "销售费用", budget: 0, real: 0, rate: 0, diff: 0, flag: 0 },
financeCostData: { title: "财务费用", budget: 0, real: 0, rate: 0, diff: 0, flag: 0 }
}
},
computed: {
indicatorDefs() {
return [
{ key: 'mgmtFee', name: '管理费用', unit: '万元'},
{ key: 'salesFee', name: '销售费用', unit: '万元'},
{ key: 'finFee', name: '财务费用', unit: '万元'}
]
},
indicators() {
let _this = this
const fallback = { budget: 0, real: 0, rate: 0, diff: 0, flag: 0 }
const list = (Array.isArray(_this.ytdAnalysis) ? _this.ytdAnalysis : [])
return _this.indicatorDefs.map(def => {
const data = list.find(item => item && item.title === def.name) || fallback
const detailData = {
...data,
flag: data.rate>=100?1:0
}
return {
...def,
detailData,
sortValue: Number((data && data.real) ?? 0)
}
})
},
sortedIndicators() {
const unitOrder = ['万元']
const unitRank = (u) => {
const idx = unitOrder.indexOf(u)
return idx === -1 ? 999 : idx
}
return this.indicators.slice().sort((a, b) => {
const ur = unitRank(a.unit) - unitRank(b.unit)
if (ur !== 0) return ur
const vr = (b.sortValue ?? -Infinity) - (a.sortValue ?? -Infinity)
if (vr !== 0) return vr
return String(a.key).localeCompare(String(b.key))
})
},
},
watch: {
ytdAnalysis: {
handler(newVal) {},
deep: true,
immediate: true // 初始化立即执行
}
}
}
</script>
<style lang='scss' scoped>
.scroll-container {
max-height: 210px;
overflow-y: auto;
overflow-x: hidden;
padding: 10px 0;
&::-webkit-scrollbar {
display: none;
}
scrollbar-width: none;
-ms-overflow-style: none;
}
.topItem-container {
display: flex;
justify-content: space-between; // 三列均匀分布
}
.dashboard {
flex: 1; // 三列等分宽度
min-width: 240px; // 最小宽度,防止挤压
max-width: 300px; // 最大宽度,限制过宽
height: 205px;
background: #F9FCFF;
padding: 16px 0 0 10px;
margin: 0 4px;
.title {
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 18px;
color: #000000;
line-height: 18px;
letter-spacing: 2px;
text-align: left;
}
// 图表容器:适配高度
.chart-wrap {
width: 100%;
height: calc(100% - 30px);
}
.number {
display: flex;
align-items: center;
gap: 30px;
height: 32px;
font-family: YouSheBiaoTiHei;
font-size: 32px;
color: #0B58FF;
line-height: 32px;
letter-spacing: 2px;
text-align: left;
}
.mom {
width: 97px;
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 18px;
color: #000000;
line-height: 18px;
letter-spacing: 1px;
text-align: left;
z-index: 1000;
}
}
</style>