This commit is contained in:
‘937886381’
2025-12-30 09:04:48 +08:00
parent 80deffbb42
commit 7b3873f9ea
232 changed files with 13127 additions and 17011 deletions

View File

@@ -10,7 +10,7 @@
background-color: rgba(249, 252, 255, 1);
">
<!-- <top-item /> -->
<dataTrendBar :chartData="chartData" />
<dataTrendBar @handleGetItemData="getData" :chartData="chartData" />
</div>
</div>
</Container>
@@ -19,134 +19,78 @@
<script>
import Container from "../components/container.vue";
import dataTrendBar from "./dataTrendBarPro.vue";
export default {
name: "ProductionStatus",
components: { Container, dataTrendBar },
props: {
salesTrendMap: {
type: Object,
default: () => ({}),
},
grossMarginTrendMap: {
type: Object,
default: () => ({}),
trendData: {
type: Array,
default: () => [],
},
},
data() {
return {
chartData: null, // 初始化 chartData 为 null
// 移除:原 chartData 定义,改为计算属性
};
},
watch: {
grossMarginTrendMap: {
handler() {
this.processChartData();
},
immediate: true,
deep: true,
},
salesTrendMap: {
handler() {
this.processChartData();
},
immediate: true,
deep: true,
// 移除:原 watch 监听配置,计算属性自动响应 trendData 变化
computed: {
/**
* chartData 计算属性:自动响应 trendData 变化,格式化并提取各字段数组
* @returns {Object} 包含6个独立数组的格式化数据
*/
chartData() {
// 初始化6个独立数组
const timeArr = []; // 格式化后的年月数组
const valueArr = []; // 实际值数组
const diffValueArr = []; // 差异值数组
const targetValueArr = []; // 目标值数组
const proportionArr = []; // 占比数组
const completedArr = []; // 完成率数组
// 遍历传入的 trendData 数组(响应式依赖,变化时自动重算)
this.trendData.forEach((item) => {
// 1. 格式化时间并推入时间数组
const yearMonth = this.formatTimeToYearMonth(item.time);
timeArr.push(yearMonth);
// 2. 提取其他字段兜底为0防止null/undefined影响图表渲染
valueArr.push(item.value ?? 0);
diffValueArr.push(item.diffValue ?? 0);
targetValueArr.push(item.targetValue ?? 0);
proportionArr.push(item.proportion ?? 0);
completedArr.push(item.completed ?? 0);
});
// 组装并返回格式化后的数据(结构与原一致)
return {
time: timeArr,
value: valueArr,
diffValue: diffValueArr,
targetValue: targetValueArr,
proportion: proportionArr,
completed: completedArr,
rawData: this.trendData, // 透传原始数据,方便子组件使用
};
},
},
methods: {
/**
* 核心处理函数:在所有数据都准备好后,才组装 chartData
* 格式化时间戳为年月格式YYYY-MM
* @param {Number} timestamp 13位毫秒级时间戳
* @returns {String} 格式化后的年月字符串2025-10
*/
processChartData() {
// 关键改动:增加数据有效性检查
// 检查 salesTrendMap 是否有实际数据(不只是空对象)
const isSalesDataReady = Object.keys(this.salesTrendMap).length > 0;
// 检查 grossMarginTrendMap 是否有实际数据
const isGrossMarginDataReady =
Object.keys(this.grossMarginTrendMap).length > 0;
// 如果任一数据未准备好,则不更新 chartData或传递一个加载中的状态
// 你可以根据业务需求调整这里的逻辑,比如:
// 1. 等待两者都准备好
// 2. 只要有一个准备好了就更新,但确保另一个有合理的默认值
// --- 方案一:等待两者都准备好 ---
// if (!isSalesDataReady || !isGrossMarginDataReady) {
// console.log('数据尚未全部准备好,暂不更新图表');
// this.chartData = {
// grossMarginLocations: [],
// salesLocations: [],
// grossMargin: { rates: [], reals: [], targets: [], flags: [] },
// sales: { rates: [], reals: [], targets: [], flags: [] },
// };
// return;
// }
// --- 方案二 (推荐):有什么数据就显示什么,没有的就显示空 ---
// 这种方式更友好,用户可以先看到部分数据
const grossMarginLocations = isGrossMarginDataReady
? Object.keys(this.grossMarginTrendMap)
: [];
const salesLocations = isSalesDataReady
? Object.keys(this.salesTrendMap)
: [];
const processedGrossMarginData = isGrossMarginDataReady
? this.processSingleDataset(
grossMarginLocations,
this.grossMarginTrendMap
)
: { rates: [], reals: [], targets: [], flags: [] };
const processedSalesData = isSalesDataReady
? this.processSingleDataset(salesLocations, this.salesTrendMap)
: { rates: [], reals: [], targets: [], flags: [] };
// 3. 组装最终的 chartData 对象
this.chartData = {
grossMarginLocations: grossMarginLocations,
salesLocations: salesLocations,
grossMargin: processedGrossMarginData,
sales: processedSalesData,
};
console.log("chartData 已更新:", this.chartData);
formatTimeToYearMonth(timestamp) {
if (!timestamp || isNaN(timestamp)) {
return ""; // 容错:非有效时间戳返回空字符串
}
const date = new Date(timestamp);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份从0开始补0至2位
return `${year}-${month}`;
},
/**
* 通用数据处理函数(纯函数)
* @param {Array} locations - 某个指标的地点数组
* @param {Object} dataMap - 该指标的原始数据映射
* @returns {Object} - 格式化后的数据对象
*/
processSingleDataset(locations, dataMap) {
const rates = [];
const reals = [];
const targets = [];
const flags = [];
locations.forEach((location) => {
const data = dataMap[location] || {};
// 优化:处理 data.rate 为 null/undefined 的情况
const rate =
data.rate !== null && data.rate !== undefined
? Math.round(data.rate * 100)
: 0;
rates.push(rate);
reals.push(data.real ?? 0); // 使用空值合并运算符
targets.push(data.target ?? 0);
// 优化:更清晰的逻辑
if (data.target === 0) {
flags.push(1); // 如果目标为0默认达标
} else {
flags.push(rate >= 100 ? 1 : 0);
}
});
return { rates, reals, targets, flags };
getData(value) {
this.$emit('getData', value)
},
},
};
@@ -285,13 +229,11 @@ export default {
top: 0;
left: 0;
height: 100%;
background: linear-gradient(
65deg,
rgba(53, 223, 247, 0) 0%,
rgba(54, 220, 246, 0.92) 92%,
#36f6e5 100%,
#37acf5 100%
);
background: linear-gradient(65deg,
rgba(53, 223, 247, 0) 0%,
rgba(54, 220, 246, 0.92) 92%,
#36f6e5 100%,
#37acf5 100%);
border-radius: 5px;
transition: width 0.3s ease;
/* 进度变化时添加过渡动画,更流畅 */