达标函数删除,图表label置于最顶层

This commit is contained in:
2026-04-14 10:17:38 +08:00
parent 0d74e762ce
commit 7135ab0e4b
208 changed files with 3567 additions and 12787 deletions

View File

@@ -27,18 +27,6 @@ export default {
type: Array,
// 默认值与实际数据结构一致12个月
default: () => [
// { title: "2025年01月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年02月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年03月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年04月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年05月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年06月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年07月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年08月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年09月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年10月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年11月", budget: 0, real: 0, rate: 0, diff: 0 },
// { title: "2025年12月", budget: 0, real: 0, rate: 0, diff: 0 }
]
},
},
@@ -98,7 +86,7 @@ export default {
const diff = Number(item.diff) || 0;
// 计算达标标识≥100 → 1<100 → 0
const flag = this.getRateFlag(rate, real, budget);
const flag = item.rate >= 100 ? 1 : 0;
// 填充数组
months.push(month);
@@ -120,25 +108,7 @@ export default {
};
console.log('处理后的趋势数据:', this.chartData);
},
/**
* 计算达标标识
* @param {Number} rate - 完成率原始值如1.2 → 120%
* @returns {Number} 1: 达标≥100%0: 未达标(<100%
*/
getRateFlag(rate, real, target) {
if (isNaN(rate) || rate === null || rate === undefined) return 0;
// 1. 完成率 >= 100 => 达标
if (rate >= 100) return 1;
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
if (rate === 0 && target === 0) return 1;
// 其他情况 => 未达标
return 0;
},
}
},
};
</script>

View File

@@ -146,76 +146,7 @@ export default {
type: 'bar',
yAxisIndex: 0,
barWidth: 14,
label: {
show: true,
position: 'top',
offset: [0, 0],
// 固定label尺寸68px×20px
width: 68,
height: 20,
// 关键:去掉换行,让文字在一行显示,适配小尺寸
formatter: (params) => {
const diff = data.diffs || [];
const flags = data.flags || [];
const currentDiff = diff[params.dataIndex] || 0;
const currentFlag = flags[params.dataIndex] || 0;
const prefix = currentFlag === 1 ? '+' : '-';
// 根据标志位选择不同的样式类
if (currentFlag === 1) {
// 达标 - 使用 rate-achieved 样式
return `{achieved|${currentDiff}}{text|差值}`;
} else {
// 未达标 - 使用 rate-unachieved 样式
return `{unachieved|${currentDiff}}{text|差值}`;
}
},
backgroundColor: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(205, 215, 224, 0.6)' },
{ offset: 0.2, color: '#ffffff' },
{ offset: 1, color: '#ffffff' }
]
},
shadowColor: 'rgba(191,203,215,0.5)',
shadowBlur: 2,
shadowOffsetX: 0,
shadowOffsetY: 2,
borderRadius: 4,
borderColor: '#BFCBD577',
borderWidth: 0,
lineHeight: 20,
rich: {
text: {
width: 'auto',
padding: [5, 10, 5, 0],
align: 'center',
color: '#464646',
fontSize: 11,
lineHeight: 20
},
achieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#76DABE', // 与达标的 offset: 1 颜色一致
fontSize: 11,
lineHeight: 20
},
// 未达标样式
unachieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#F9A44A', // 与未达标的 offset: 1 颜色一致
fontSize: 11,
lineHeight: 20
}
}
},
label: { show: false },
itemStyle: {
color: (params) => {
// 达标状态1=达标绿色0=未达标(橙色)
@@ -243,6 +174,79 @@ export default {
borderWidth: 0
},
data: data.reals // 实际销量(万元)
},
// 实际柱状图的标签层独立scatter系列zlevel=1确保标签在最上层
{
name: '__实际差值标签',
type: 'scatter',
yAxisIndex: 0,
zlevel: 1,
symbolSize: 0,
tooltip: { show: false },
data: (data.reals || []).map((value, index) => ({
value: value,
label: {
show: true,
position: 'top',
offset: [0, 0],
width: 68,
height: 20,
formatter: () => {
const diff = data.diffs || [];
const flags = data.flags || [];
const currentDiff = diff[index] || 0;
const currentFlag = flags[index] || 0;
if (currentFlag === 1) {
return `{achieved|${currentDiff}}{text|差值}`;
} else {
return `{unachieved|${currentDiff}}{text|差值}`;
}
},
backgroundColor: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(205, 215, 224, 0.6)' },
{ offset: 0.2, color: '#ffffff' },
{ offset: 1, color: '#ffffff' }
]
},
shadowColor: 'rgba(191,203,215,0.5)',
shadowBlur: 2,
shadowOffsetX: 0,
shadowOffsetY: 2,
borderRadius: 4,
borderColor: '#BFCBD577',
borderWidth: 0,
lineHeight: 20,
rich: {
text: {
width: 'auto',
padding: [5, 10, 5, 0],
align: 'center',
color: '#464646',
fontSize: 11,
lineHeight: 20
},
achieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#76DABE',
fontSize: 11,
lineHeight: 20
},
unachieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#F9A44A',
fontSize: 11,
lineHeight: 20
}
}
}
}))
}
]
};

View File

@@ -19,9 +19,6 @@
<img v-else class="arrow" src="../../../assets/img/downArrow.png" alt="">
</div>
</div>
<!-- <div class="electricityGauge">
<electricityGauge :detailData="monthData" id="month"></electricityGauge>
</div> -->
</div>
<div class="line" style="padding: 0px;">
<verticalBarChart :detailData="monthData">
@@ -38,9 +35,6 @@ import Container from './container.vue'
import electricityGauge from './electricityGauge.vue'
import verticalBarChart from './verticalBarChart.vue'
// import * as echarts from 'echarts'
// import rawItem from './raw-Item.vue'
export default {
name: 'ProductionStatus',
components: { Container, electricityGauge, verticalBarChart },
@@ -74,21 +68,6 @@ export default {
deep: true // 若对象内属性变化需触发,需加 deep: true
}
},
// computed: {
// // 处理排序:包含“总成本”的项放前面,其余项按原顺序排列
// sortedItemData() {
// // 过滤出包含“总成本”的项(不区分大小写)
// const totalCostItems = this.itemData.filter(item =>
// item.name && item.name.includes('总成本')
// );
// // 过滤出不包含“总成本”的项
// const otherItems = this.itemData.filter(item =>
// !item.name || !item.name.includes('总成本')
// );
// // 合并:总成本项在前,其他项在后
// return [...totalCostItems, ...otherItems];
// }
// },
mounted() {
// 初始化图表(若需展示图表,需在模板中添加对应 DOM
// this.$nextTick(() => this.updateChart())

View File

@@ -96,18 +96,6 @@ export default {
}
})
},
getRateFlag(rate, real, target) {
if (isNaN(rate) || rate === null || rate === undefined) return 0;
// 1. 完成率 >= 100 => 达标
if (rate >= 100) return 1;
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
if (rate === 0 && target === 0) return 1;
// 其他情况 => 未达标
return 0;
},
updateChart(data) {
// 修复核心:正确获取默认值(调用 factory 函数)
@@ -124,12 +112,12 @@ getRateFlag(rate, real, target) {
// 整合flag字段
this.ytdIncomeData = {
...incomeItem,
flag: this.getRateFlag(incomeItem.rate, incomeItem.real, incomeItem.budget)
flag: incomeItem.rate > 100 ? 1 : 0
};
this.ytdCostData = {
...costItem,
flag: this.getRateFlag(costItem.rate, costItem.real, costItem.budget)
flag: costItem.rate > 100 ? 1 : 0
};
console.log('累计收入数据:', this.ytdIncomeData);

View File

@@ -174,71 +174,7 @@ export default {
type: 'bar',
yAxisIndex: 0,
barWidth: 40,
label: {
show: true,
position: 'top',
offset: [32, 0],
width: 100,
height: 22,
formatter: (params) => {
const diff = data.diff || [];
const flags = data.flags || [];
const currentDiff = diff[params.dataIndex] || 0;
const currentFlag = flags[params.dataIndex] || 0;
const prefix = currentFlag === 1 ? '+' : '-';
// 根据标志位选择不同的样式类
if (currentFlag === 1) {
// 达标 - 使用 rate-achieved 样式
return `{achieved|${currentDiff}}{text|差值}`;
} else {
// 未达标 - 使用 rate-unachieved 样式
return `{unachieved|${currentDiff}}{text|差值}`;
}
},
backgroundColor: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(205, 215, 224, 0.6)' },
{ offset: 0.2, color: '#ffffff' },
{ offset: 1, color: '#ffffff' }
]
},
shadowColor: 'rgba(191,203,215,0.5)',
shadowBlur: 2,
shadowOffsetX: 0,
shadowOffsetY: 2,
borderRadius: 4,
borderColor: '#BFCBD577',
borderWidth: 0,
lineHeight: 26,
rich: {
text: {
width: 'auto',
padding: [5, 10, 5, 0],
align: 'center',
color: '#464646',
fontSize: 14
},
achieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#76DABE', // 与达标的 offset: 1 颜色一致
fontSize: 14
},
// 未达标样式
unachieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#F9A44A', // 与未达标的 offset: 1 颜色一致
fontSize: 14
}
}
},
label: { show: false },
itemStyle: {
color: (params) => {
const safeFlag = data.flags || [];
@@ -265,6 +201,76 @@ export default {
borderWidth: 0
},
data: data.reals || []
},
// 实际柱状图的标签层独立scatter系列zlevel=1确保标签在最上层
{
name: '__实际差值标签',
type: 'scatter',
yAxisIndex: 0,
zlevel: 1,
symbolSize: 0,
tooltip: { show: false },
data: (data.reals || []).map((value, index) => ({
value: value,
label: {
show: true,
position: 'top',
offset: [32, 0],
width: 100,
height: 22,
formatter: () => {
const diff = data.diff || [];
const flags = data.flags || [];
const currentDiff = diff[index] || 0;
const currentFlag = flags[index] || 0;
if (currentFlag === 1) {
return `{achieved|${currentDiff}}{text|差值}`;
} else {
return `{unachieved|${currentDiff}}{text|差值}`;
}
},
backgroundColor: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(205, 215, 224, 0.6)' },
{ offset: 0.2, color: '#ffffff' },
{ offset: 1, color: '#ffffff' }
]
},
shadowColor: 'rgba(191,203,215,0.5)',
shadowBlur: 2,
shadowOffsetX: 0,
shadowOffsetY: 2,
borderRadius: 4,
borderColor: '#BFCBD577',
borderWidth: 0,
lineHeight: 26,
rich: {
text: {
width: 'auto',
padding: [5, 10, 5, 0],
align: 'center',
color: '#464646',
fontSize: 14
},
achieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#76DABE',
fontSize: 14
},
unachieved: {
width: 'auto',
padding: [5, 0, 5, 10],
align: 'center',
color: '#F9A44A',
fontSize: 14
}
}
}
}))
}
]
};

View File

@@ -17,10 +17,6 @@ export default {
type: Object,
default: () => ({
}),
// 校验数据格式
// validator: (value) => {
// return Array.isArray(value.series) && Array.isArray(value.allPlaceNames);
// }
}
},
mounted() {
@@ -72,16 +68,6 @@ export default {
backgroundColor: '#6a7985'
}
},
// formatter: (params) => {
// let html = `${params[0].axisValue}<br/>`;
// params.forEach(item => {
// const unit = item.seriesName === '完成率' ? '%' : (
// ['产量', '销量'].includes(this.$parent.selectedProfit) ? '片' : '万元'
// );
// html += `${item.marker} ${item.seriesName}: ${item.value}${unit}<br/>`;
// });
// return html;
// }
},
grid: {
top: 30,

View File

@@ -118,7 +118,7 @@ getRateFlag(rate, real, target) {
const groupReal = [this.groupData.real]; // 实际值数组
const groupRate = [this.groupData.rate]; // 完成率数组
// 新增集团rate对应的flag
const groupFlag = [this.getRateFlag(groupRate[0], groupReal[0], groupTarget[0])];
const groupFlag = [this.groupData.rate >=100 ? 1 : 0];
console.log('集团数据数组:', {
groupTarget,
@@ -139,7 +139,7 @@ getRateFlag(rate, real, target) {
const factoryRate = this.factoryData.map(item => item.rate || 0);
const factoryDiff = this.factoryData.map(item => item.diff || 0);
// 新增每个工厂rate对应的flag数组
const factoryFlags = this.factoryData.map(item => this.getRateFlag(item.rate, item.real, item.budget));
const factoryFlags = this.factoryData.map(item => item.rate >=100 ? 1 : 0);
// 3. 组装最终的chartData供子组件使用
this.chartData = {

View File

@@ -81,24 +81,6 @@ export default {
sortChange(value) {
this.$emit('sort-change', value);
},
/**
* 判断rate对应的flag值<1为0>1为1
* @param {number} rate 处理后的rate值已*100
* @returns {0|1} flag值
*/
getRateFlag(rate, real, target) {
if (isNaN(rate) || rate === null || rate === undefined) return 0;
// 1. 完成率 >= 100 => 达标
if (rate >= 100) return 1;
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
if (rate === 0 && target === 0) return 1;
// 其他情况 => 未达标
return 0;
},
/**
* 核心处理函数:在所有数据都准备好后,才组装 chartData
@@ -113,7 +95,7 @@ getRateFlag(rate, real, target) {
const groupReal = [this.groupData.real]; // 实际值数组
const groupRate = [this.groupData.rate]; // 完成率数组
// 新增集团rate对应的flag
const groupFlag = [this.getRateFlag(groupRate[0], groupReal[0], groupTarget[0])];
const groupFlag = [this.groupData.rate > 100 ? 1 : 0];
console.log('集团数据数组:', {
groupTarget,
@@ -134,7 +116,7 @@ getRateFlag(rate, real, target) {
const factoryRate = this.factoryData.map(item => item.rate || 0);
const factoryDiff = this.factoryData.map(item => item.diff || 0);
// 新增每个工厂rate对应的flag数组
const factoryFlags = this.factoryData.map(item => this.getRateFlag(item.rate, item.rate, item.budget));
const factoryFlags = this.factoryData.map(item => item.rate > 100 ? 1 : 0);
// 3. 组装最终的chartData供子组件使用
this.chartData = {

View File

@@ -40,33 +40,6 @@ export default {
const salesData = {
allPlaceNames: this.locations,
series: [
// 1. 完成率(折线图)
// {
// name: '完成率',
// type: 'line',
// yAxisIndex: 1, // 绑定右侧Y轴需在子组件启用配置
// lineStyle: {
// color: 'rgba(40, 138, 255, .5)',
// width: 2
// },
// itemStyle: {
// color: 'rgba(40, 138, 255, 1)',
// borderColor: 'rgba(40, 138, 255, 1)',
// borderWidth: 2,
// radius: 4
// },
// areaStyle: {
// opacity: 0.2,
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// { offset: 0, color: 'rgba(40, 138, 255, .9)' },
// { offset: 1, color: 'rgba(40, 138, 255, 0)' }
// ])
// },
// data: data.rates, // 完成率(%
// symbol: 'circle',
// symbolSize: 6
// },
// 2. 目标(柱状图)
{
name: '预算',
type: 'bar',

View File

@@ -19,9 +19,6 @@
<img v-else class="arrow" src="../../../assets/img/downArrow.png" alt="">
</div>
</div>
<!-- <div class="electricityGauge">
<electricityGauge :id="'totalG'" :detailData="ytdData" id="totalGauge"></electricityGauge>
</div> -->
</div>
<div class="line" style="padding: 0px;">
<verticalBarChart :refName="'totalVerticalBarChart'" :detailData="ytdData">
@@ -38,9 +35,6 @@ import Container from './container.vue'
import electricityGauge from './electricityGauge.vue'
import verticalBarChart from './verticalBarChart.vue'
// import * as echarts from 'echarts'
// import rawItem from './raw-Item.vue'
export default {
name: 'ProductionStatus',
components: { Container, electricityGauge, verticalBarChart },
@@ -73,21 +67,6 @@ export default {
deep: true // 若对象内属性变化需触发,需加 deep: true
}
},
// computed: {
// // 处理排序:包含“总成本”的项放前面,其余项按原顺序排列
// sortedItemData() {
// // 过滤出包含“总成本”的项(不区分大小写)
// const totalCostItems = this.itemData.filter(item =>
// item.name && item.name.includes('总成本')
// );
// // 过滤出不包含“总成本”的项
// const otherItems = this.itemData.filter(item =>
// !item.name || !item.name.includes('总成本')
// );
// // 合并:总成本项在前,其他项在后
// return [...totalCostItems, ...otherItems];
// }
// },
mounted() {
// 初始化图表(若需展示图表,需在模板中添加对应 DOM
// this.$nextTick(() => this.updateChart())

View File

@@ -50,18 +50,6 @@ export default {
}
},
methods: {
getRateFlag(rate, real, target) {
if (isNaN(rate) || rate === null || rate === undefined) return 0;
// 1. 完成率 >= 100 => 达标
if (rate >= 100) return 1;
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
if (rate === 0 && target === 0) return 1;
// 其他情况 => 未达标
return 0;
},
updateChart() {
const chartDom = this.$refs[this.refName];
if (!chartDom) {
@@ -76,7 +64,7 @@ export default {
this.myChart = echarts.init(chartDom);
const diff = this.detailData.diff || 0
const rate = this.detailData.rate || 0
const flagValue = this.getRateFlag(this.detailData.rate, this.detailData.real, this.detailData.target) || 0
const flagValue = this.detailData.rate>=100?1:0
this.flag = flagValue
const option = {
@@ -88,16 +76,6 @@ export default {
backgroundColor: '#6a7985'
}
},
// formatter: (params) => {
// let html = `${params[0].axisValue}<br/>`;
// params.forEach(item => {
// const unit = item.seriesName === '完成率' ? '%' : (
// ['产量', '销量'].includes(this.$parent.selectedProfit) ? '片' : '万元'
// );
// html += `${item.marker} ${item.seriesName}: ${item.value}${unit}<br/>`;
// });
// return html;
// }
},
grid: {
top: 40,
@@ -110,9 +88,6 @@ export default {
xAxis: {
// 横向柱状图的x轴必须设为数值轴否则无法正常展示数值
type: 'value',
// offset: 0,
// boundaryGap: true ,
// boundaryGap: [10, 0], // 可根据需要开启,控制轴的留白
axisTick: { show: false },
min: 0,
//

View File

@@ -101,19 +101,6 @@ export default {
}
})
},
// 保留原flag判断逻辑≥100返回1<100返回0
getRateFlag(rate, real, target) {
if (isNaN(rate) || rate === null || rate === undefined) return 0;
// 1. 完成率 >= 100 => 达标
if (rate >= 100) return 1;
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
if (rate === 0 && target === 0) return 1;
// 其他情况 => 未达标
return 0;
},
updateChart(data) {
// 数据兜底确保是数组且长度≥2
@@ -128,12 +115,12 @@ export default {
// 整合flag字段到收入/全成本数据中
this.incomeData = {
...incomeItem,
flag: this.getRateFlag(incomeItem.rate, incomeItem.real, incomeItem.budget)
flag: incomeItem.rate >= 100 ? 1 : 0
};
this.totalCostData = {
...totalCostItem,
flag: this.getRateFlag(totalCostItem.rate, totalCostItem.real, totalCostItem.budget)
flag: totalCostItem.rate >= 100 ? 1 : 0
};
// 调试:确认数据赋值正确