431 lines
11 KiB
Vue
431 lines
11 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<!-- 顶部日期&筛选栏 -->
|
||
<el-row :gutter="20" class="top-bar">
|
||
<el-col :span="8">
|
||
<el-date-picker
|
||
v-model="dateRange"
|
||
type="daterange"
|
||
range-separator="~"
|
||
start-placeholder="开始日期"
|
||
end-placeholder="结束日期"
|
||
value-format="yyyy-MM-dd" />
|
||
<el-button type="primary" style="margin-left: 10px">查询</el-button>
|
||
</el-col>
|
||
<el-col :span="16">
|
||
<el-tag type="info" @click="changeTime('yesterday')">昨日</el-tag>
|
||
<el-tag type="info" @click="changeTime('week')">本周</el-tag>
|
||
<el-tag type="info" @click="changeTime('month')">本月</el-tag>
|
||
<el-tag type="info" @click="changeTime('year')">本年</el-tag>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 成本概览卡片 -->
|
||
<el-row :gutter="20" class="card-row">
|
||
<el-col :span="8">
|
||
<el-card class="cost-card">
|
||
<div class="card-title">总制造成本(元/平米)</div>
|
||
<div class="card-content">
|
||
<div>
|
||
目标
|
||
<span class="target-val">16</span>
|
||
</div>
|
||
<div>
|
||
实际
|
||
<span class="actual-val">12.8</span>
|
||
</div>
|
||
<el-progress :stroke-width="13" :percentage="80" color="#42b983" />
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-card class="cost-card">
|
||
<div class="card-title">原片成本(元/平米)</div>
|
||
<div class="card-content">
|
||
<div>
|
||
目标
|
||
<span class="target-val">16</span>
|
||
</div>
|
||
<div>
|
||
实际
|
||
<span class="actual-val">12.8</span>
|
||
</div>
|
||
<el-progress :stroke-width="13" :percentage="99" color="#42b983" />
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-card class="cost-card">
|
||
<div class="card-title">加工成本(元/平米)</div>
|
||
<div class="card-content">
|
||
<div>
|
||
目标
|
||
<span class="target-val">16</span>
|
||
</div>
|
||
<div>
|
||
实际
|
||
<span class="actual-val">12.8</span>
|
||
</div>
|
||
<el-progress :stroke-width="13" :percentage="99" color="#42b983" />
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 成本构成区域 -->
|
||
<el-row :gutter="20" class="composition-row">
|
||
<!-- 饼图 -->
|
||
<el-col :span="6">
|
||
<el-card class="composition-card">
|
||
<div class="card-title">成本构成</div>
|
||
<div id="costPie" class="chart" style="height: 350px"></div>
|
||
</el-card>
|
||
</el-col>
|
||
<!-- 原片/加工成本子项 -->
|
||
<el-col :span="18">
|
||
<el-card class="composition-card">
|
||
<div class="card-title">成本构成</div>
|
||
|
||
<!-- 原片成本子项 -->
|
||
<div class="sub-cost-group">
|
||
<div class="sub-cost-title">原片成本</div>
|
||
<div class="sub-cost">
|
||
<div
|
||
v-for="(item, idx) in rawSubCosts"
|
||
:key="idx"
|
||
class="sub-cost-div">
|
||
<div class="sub-cost-name">
|
||
{{ item.name }}
|
||
<div class="sub-cost-val">{{ item.val }}</div>
|
||
</div>
|
||
<div style="text-align: center">
|
||
<el-progress
|
||
type="circle"
|
||
:percentage="89"
|
||
:width="60"
|
||
:stroke-width="10"
|
||
:show-text="false"
|
||
color="#e74c3c" />
|
||
</div>
|
||
<div class="sub-cost-name">
|
||
目标
|
||
<span class="red-text">{{ item.target }}</span>
|
||
</div>
|
||
<div class="sub-cost-name">
|
||
完成率
|
||
<span class="red-text">89%</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<el-divider></el-divider>
|
||
<!-- 加工成本子项 -->
|
||
<div class="sub-cost-group" style="margin-top: 20px">
|
||
<div class="sub-cost-title">加工成本</div>
|
||
<div class="sub-cost">
|
||
<div
|
||
v-for="(item, idx) in processSubCosts"
|
||
:key="idx"
|
||
class="sub-cost-div">
|
||
<div class="sub-cost-name">
|
||
{{ item.name }}
|
||
<div class="sub-cost-val">{{ item.val }}</div>
|
||
</div>
|
||
<div style="text-align: center">
|
||
<el-progress
|
||
type="circle"
|
||
:percentage="89"
|
||
:width="60"
|
||
:stroke-width="10"
|
||
:show-text="false"
|
||
color="#e74c3c" />
|
||
</div>
|
||
<div class="sub-cost-name">
|
||
目标
|
||
<span class="red-text">{{ item.target }}</span>
|
||
</div>
|
||
<div class="sub-cost-name">
|
||
完成率
|
||
<span class="red-text">89%</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 趋势图区域 -->
|
||
<el-row :gutter="20" class="trend-row">
|
||
<!-- 总制造成本趋势 -->
|
||
<el-col :span="8">
|
||
<el-card class="trend-card">
|
||
<div class="card-title">总制造成本趋势</div>
|
||
<div id="totalTrend" class="chart" style="height: 300px"></div>
|
||
</el-card>
|
||
</el-col>
|
||
<!-- 原片/加工成本趋势 -->
|
||
<el-col :span="8">
|
||
<el-card class="trend-card">
|
||
<div class="card-title">原片/加工成本趋势</div>
|
||
<el-tabs v-model="costTab" type="card" style="margin-bottom: 10px">
|
||
<el-tab-pane label="原片成本" name="raw"></el-tab-pane>
|
||
<el-tab-pane label="加工成本" name="process"></el-tab-pane>
|
||
</el-tabs>
|
||
<div id="rawProcessTrend" class="chart" style="height: 300px"></div>
|
||
</el-card>
|
||
</el-col>
|
||
<!-- 单项成本趋势 -->
|
||
<el-col :span="8">
|
||
<el-card class="trend-card">
|
||
<div class="card-title">单项成本趋势</div>
|
||
<el-tabs v-model="itemTab" type="card" style="margin-bottom: 10px">
|
||
<el-tab-pane label="人工成本" name="labor"></el-tab-pane>
|
||
<el-tab-pane label="原料成本" name="material"></el-tab-pane>
|
||
<el-tab-pane label="制造费用" name="expense"></el-tab-pane>
|
||
<el-tab-pane label="玻璃热耗" name="heat"></el-tab-pane>
|
||
<el-tab-pane label="原片成品率" name="yield"></el-tab-pane>
|
||
</el-tabs>
|
||
<div id="itemTrend" class="chart" style="height: 300px"></div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import * as echarts from 'echarts';
|
||
|
||
export default {
|
||
name: 'CostDashboard',
|
||
data() {
|
||
return {
|
||
dateRange: ['2023-05-06', '2023-05-06'],
|
||
costTab: 'raw',
|
||
itemTab: 'labor',
|
||
// 原片成本子项
|
||
rawSubCosts: [
|
||
{ name: '人工成本', val: 4.56, target: 4.32 },
|
||
{ name: '原料成本', val: 4.56, target: 4.32 },
|
||
{ name: '原片制造费用', val: 4.56, target: 4.32 },
|
||
{ name: '玻璃热耗', val: 4.56, target: 4.32 },
|
||
{ name: '原片成品率', val: 4.56, target: 4.32 },
|
||
],
|
||
// 加工成本子项
|
||
processSubCosts: [
|
||
{ name: '人工成本', val: 4.56, target: 4.32 },
|
||
{ name: '加工动力成本', val: 4.56, target: 4.32 },
|
||
{ name: '加工制造费用', val: 4.56, target: 4.32 },
|
||
{ name: '加工投入产出率', val: 4.56, target: 4.32 },
|
||
],
|
||
// 趋势图模拟数据
|
||
trendX: ['00:00', '01:00', '02:00'],
|
||
trendY: [20, 40, 50],
|
||
targetY: 12.54,
|
||
};
|
||
},
|
||
mounted() {
|
||
this.initCostPie();
|
||
this.initTotalTrend();
|
||
this.initRawProcessTrend();
|
||
this.initItemTrend();
|
||
},
|
||
methods: {
|
||
// 切换时间范围(示例)
|
||
changeTime(type) {
|
||
// 实际项目中需根据type请求对应数据
|
||
console.log('切换时间:', type);
|
||
},
|
||
// 初始化成本构成饼图
|
||
initCostPie() {
|
||
const pieChart = echarts.init(document.getElementById('costPie'));
|
||
pieChart.setOption({
|
||
tooltip: { trigger: 'item' },
|
||
legend: {
|
||
orient: 'horizontal', // 水平排列
|
||
bottom: 0, // 放在底部
|
||
icon: 'circle',
|
||
left: 'center',
|
||
formatter: function (name) {
|
||
return name;
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
type: 'pie',
|
||
data: [
|
||
{ name: '原料成本(4.2元)', value: 29.9 },
|
||
{ name: '动力成本(2.1元)', value: 24 },
|
||
{ name: '人工成本(1.5元)', value: 24 },
|
||
{ name: '辅料成本(0.5元)', value: 21.2 },
|
||
{ name: '制造费用(0.5元)', value: 21.2 },
|
||
],
|
||
label: { show: false },
|
||
labelLine: { show: false },
|
||
bottom: 10,
|
||
},
|
||
],
|
||
});
|
||
window.addEventListener('resize', () => pieChart.resize());
|
||
},
|
||
// 初始化总制造成本趋势图
|
||
initTotalTrend() {
|
||
const totalChart = echarts.init(document.getElementById('totalTrend'));
|
||
totalChart.setOption({
|
||
grid: { top: 20, bottom: 30, left: 30, right: 10 },
|
||
xAxis: { type: 'category', data: this.trendX },
|
||
yAxis: { type: 'value', min: -20, max: 60 },
|
||
series: [
|
||
{
|
||
name: '实际值',
|
||
type: 'line',
|
||
data: this.trendY,
|
||
lineStyle: { color: '#409eff' },
|
||
},
|
||
{
|
||
name: '目标值',
|
||
type: 'line',
|
||
data: [this.targetY, this.targetY, this.targetY],
|
||
lineStyle: { type: 'dashed', color: '#e6a23c' },
|
||
},
|
||
],
|
||
});
|
||
window.addEventListener('resize', () => totalChart.resize());
|
||
},
|
||
// 初始化原片/加工成本趋势图
|
||
initRawProcessTrend() {
|
||
const rpChart = echarts.init(document.getElementById('rawProcessTrend'));
|
||
rpChart.setOption({
|
||
grid: { top: 10, bottom: 20, left: 20, right: 10 },
|
||
xAxis: { type: 'category', data: this.trendX },
|
||
yAxis: { type: 'value', min: -20, max: 60 },
|
||
series: [
|
||
{
|
||
name: '实际值',
|
||
type: 'line',
|
||
data: this.trendY,
|
||
lineStyle: { color: '#409eff' },
|
||
},
|
||
{
|
||
name: '目标值',
|
||
type: 'line',
|
||
data: [this.targetY, this.targetY, this.targetY],
|
||
lineStyle: { type: 'dashed', color: '#e6a23c' },
|
||
},
|
||
],
|
||
});
|
||
window.addEventListener('resize', () => rpChart.resize());
|
||
},
|
||
// 初始化单项成本趋势图
|
||
initItemTrend() {
|
||
const itemChart = echarts.init(document.getElementById('itemTrend'));
|
||
itemChart.setOption({
|
||
grid: { top: 10, bottom: 20, left: 20, right: 10 },
|
||
xAxis: { type: 'category', data: this.trendX },
|
||
yAxis: { type: 'value', min: -20, max: 60 },
|
||
series: [
|
||
{
|
||
name: '实际值',
|
||
type: 'line',
|
||
data: this.trendY,
|
||
lineStyle: { color: '#409eff' },
|
||
},
|
||
{
|
||
name: '目标值',
|
||
type: 'line',
|
||
data: [this.targetY, this.targetY, this.targetY],
|
||
lineStyle: { type: 'dashed', color: '#e6a23c' },
|
||
},
|
||
],
|
||
});
|
||
window.addEventListener('resize', () => itemChart.resize());
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.top-bar {
|
||
margin-bottom: 20px;
|
||
}
|
||
.card-row,
|
||
.composition-row {
|
||
margin-bottom: 20px;
|
||
}
|
||
.cost-card .card-title {
|
||
font-size: 22px;
|
||
font-weight: bold;
|
||
margin-bottom: 15px;
|
||
}
|
||
.cost-card .card-content {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr;
|
||
gap: 10px;
|
||
align-items: center;
|
||
font-size: 18px;
|
||
}
|
||
.target-val {
|
||
color: #666;
|
||
margin-left: 5px;
|
||
font-size: 20px;
|
||
}
|
||
.actual-val {
|
||
color: #42b983;
|
||
margin-left: 5px;
|
||
font-size: 20px;
|
||
}
|
||
.composition-card {
|
||
height: 480px;
|
||
}
|
||
.composition-card .card-title {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
margin-bottom: 15px;
|
||
}
|
||
.sub-cost {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||
gap: 10px;
|
||
align-items: center;
|
||
}
|
||
.sub-cost-group .sub-cost-title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
margin-bottom: 10px;
|
||
}
|
||
.sub-cost-group .sub-cost-div {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 10px;
|
||
align-items: center;
|
||
border: 1px solid rgb(220, 220, 220, 0.5);
|
||
padding: 10px;
|
||
}
|
||
.sub-cost-name {
|
||
text-align: center;
|
||
margin-top: 5px;
|
||
font-size: 14px;
|
||
}
|
||
.sub-cost-val {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
}
|
||
.completion {
|
||
text-align: center;
|
||
font-size: 12px;
|
||
color: #666;
|
||
}
|
||
.red-text {
|
||
color: #e74c3c;
|
||
}
|
||
.trend-card {
|
||
height: 450px;
|
||
}
|
||
.trend-card .card-title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
margin-bottom: 10px;
|
||
}
|
||
</style>
|