148 lines
4.3 KiB
Vue
148 lines
4.3 KiB
Vue
·<template>
|
||
<div style="flex: 1">
|
||
<Container name="概览趋势图" icon="cockpitItemIcon" size="costSmallBg" topSize="psiTopTitleBasic">
|
||
<div class="kpi-content" style="padding: 14px 16px; display: flex;width: 100%;">
|
||
<div class="bottom" style="height: 380px; display: flex; width: 100%;background-color: rgba(249, 252, 255, 1);">
|
||
<profitBar :cost-group-data="costGroupData" :cost-types="costTypes"
|
||
:locations="locations"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</Container>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import Container from './container.vue'
|
||
import profitBar from './profitBar.vue'
|
||
|
||
export default {
|
||
name: 'ProductionStatus',
|
||
components: { Container, profitBar },
|
||
props: {
|
||
trendViews: {
|
||
type: Array,
|
||
default: () => []
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
chart: null
|
||
}
|
||
},
|
||
computed: {
|
||
// 1. 地名数组(去重,按出现顺序)
|
||
locations() {
|
||
const locationSet = new Set();
|
||
this.trendViews.forEach(item => {
|
||
const location = this.extractLocation(item.name);
|
||
if (location) locationSet.add(location);
|
||
});
|
||
return Array.from(locationSet);
|
||
},
|
||
// 2. 核心成本类型数组(仅保留“原片”“加工”等,去掉“成本”二字)
|
||
costTypes() {
|
||
const typeSet = new Set();
|
||
this.trendViews.forEach(item => {
|
||
const coreType = this.extractCoreCostType(item.name);
|
||
if (coreType) typeSet.add(coreType);
|
||
});
|
||
return Array.from(typeSet);
|
||
},
|
||
// 3. 按「核心成本类型+地名」分组的数据
|
||
costGroupData() {
|
||
return this.trendViews.reduce((group, item) => {
|
||
const coreType = this.extractCoreCostType(item.name) || '其他';
|
||
const location = this.extractLocation(item.name) || '未知地区';
|
||
|
||
// 初始化层级分组
|
||
if (!group[coreType]) group[coreType] = {};
|
||
if (!group[coreType][location]) group[coreType][location] = [];
|
||
|
||
// 添加数据
|
||
group[coreType][location].push({
|
||
name: item.name,
|
||
target: item.target ?? 0,
|
||
value: item.value ?? 0,
|
||
proportion: item.proportion ?? 0,
|
||
flag: item.flag ?? 0,
|
||
time: item.time
|
||
});
|
||
|
||
return group;
|
||
}, {});
|
||
}
|
||
},
|
||
methods: {
|
||
// 提取核心成本类型(仅保留“原片”“加工”等,去掉“成本”二字)
|
||
extractCoreCostType(name) {
|
||
// 匹配“前缀(含分公司/工厂/区域等)+ 核心词 + 任意后缀”,提取中间核心词
|
||
// 兼容后缀:成本、费用、支出、损耗等,前缀:XX分公司、XX工厂、XX区域等
|
||
const match = name.match(/(分公司)\s*([^,。;!?]+?)\s*(成本)/);
|
||
if (match) {
|
||
return match[2].trim(); // 提取中间核心词,去除前后空格
|
||
}
|
||
|
||
// 通用匹配:无明确前缀标识时,提取“最后一个连续汉字后缀”前的内容
|
||
const generalMatch = name.match(/(.+?)(?=[\u4e00-\u9fa5]{2,}$)/);
|
||
return generalMatch ? generalMatch[1].trim() : name.trim();
|
||
},
|
||
// 提取地名(成本类型前的核心地区名)
|
||
extractLocation(name) {
|
||
// 匹配“分公司”前面的连续汉字(即地名)
|
||
const match = name.match(/(.+?)分公司/);
|
||
|
||
if (match) {
|
||
return match[1].trim() || '未知地区';
|
||
}
|
||
|
||
// 兜底(处理不含“分公司”的情况)
|
||
return '未知地区';
|
||
}
|
||
},
|
||
watch: {
|
||
trendViews: {
|
||
handler(newValue) {
|
||
console.log('核心成本类型:', this.costTypes); // 示例输出:["原片", "加工"]
|
||
console.log('地名数组:', this.locations); // 示例输出:["桐城", "合肥"]
|
||
console.log('分组数据:', this.costGroupData);
|
||
},
|
||
deep: true
|
||
}
|
||
},
|
||
mounted() {
|
||
console.log('初始核心成本类型:', this.costTypes);
|
||
}
|
||
};
|
||
</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;
|
||
}
|
||
|
||
/* 其他样式省略 */
|
||
</style>
|
||
|
||
<style>
|
||
.production-status-chart-tooltip {
|
||
background: #0a2b4f77 !important;
|
||
border: none !important;
|
||
backdrop-filter: blur(12px);
|
||
}
|
||
|
||
.production-status-chart-tooltip * {
|
||
color: #fff !important;
|
||
}
|
||
</style>
|