运营驾驶舱对接

This commit is contained in:
2026-03-31 15:13:13 +08:00
parent 05fe91618c
commit 161d6a1bdf
44 changed files with 625 additions and 522 deletions

View File

@@ -15,6 +15,8 @@ VUE_APP_BASE_API = 'http://172.16.20.218:7070'
# VUE_APP_BASE_API = 'http://172.16.19.232:7070' # VUE_APP_BASE_API = 'http://172.16.19.232:7070'
# 测试 # 测试
# VUE_APP_BASE_API = 'http://192.168.0.35:8080' # VUE_APP_BASE_API = 'http://192.168.0.35:8080'
# 闫阳
# VUE_APP_BASE_API = 'http://172.16.19.131:7070'
# 路由懒加载 # 路由懒加载

View File

@@ -346,3 +346,38 @@ export function getDictListData(query) {
params: query, params: query,
}); });
} }
export function getAccountsReceivableData(data) {
return request({
url: "/lb/accounts-receivable/getGroupData",
method: "post",
data: data,
});
}
export function getInventoryData(data) {
return request({
url: "/lb/inventory/getGroupData",
method: "post",
data: data,
});
}
export function getElectricityCostAnalysisData(data) {
return request({
url: "/lb/electricity-cost-analysis/getGroupData",
method: "post",
data: data,
});
}
export function getDepreciationAnalysisData(data) {
return request({
url: "/lb/depreciation-analysis/getGroupData",
method: "post",
data: data,
});
}
export function getElectricityCostAnalysisFData(data) {
return request({
url: "/lb/electricity-cost-analysis/getFactoryData",
method: "post",
data: data,
});
}

View File

@@ -96,6 +96,7 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
"/salesVolumeAnalysis", "/salesVolumeAnalysis",
'/procurementGainAnalysis', '/procurementGainAnalysis',
'/fullCostAnalysis', '/fullCostAnalysis',
'/electricityCostAnalysis',
// '/expenseAnalysis', // '/expenseAnalysis',
"/cost", // cost 根路由 "/cost", // cost 根路由
"/cost/profitImpactAnalysis", // cost 子菜单(完整路径) "/cost/profitImpactAnalysis", // cost 子菜单(完整路径)

View File

@@ -39,7 +39,7 @@ import { mapState } from "vuex";
import operatingLineChart from "../accountsReceivableComponents/operatingLineChart"; import operatingLineChart from "../accountsReceivableComponents/operatingLineChart";
import operatingLineChartCumulative from "../accountsReceivableComponents/operatingLineChartCumulative.vue"; import operatingLineChartCumulative from "../accountsReceivableComponents/operatingLineChartCumulative.vue";
import { getSalesRevenueGroupData } from '@/api/cockpit' import { getAccountsReceivableData } from '@/api/cockpit'
export default { export default {
name: "AccountsReceivable", name: "AccountsReceivable",
components: { components: {
@@ -59,6 +59,7 @@ export default {
selectDate:{}, selectDate:{},
monthData: {}, monthData: {},
ytdData:{}, ytdData:{},
dateData: {},
}; };
}, },
@@ -132,15 +133,14 @@ export default {
// this.getData() // this.getData()
// }, // },
getData() { getData() {
getSalesRevenueGroupData({ getAccountsReceivableData({
startTime: this.dateData.startTime, startTime: this.dateData.startTime,
endTime: this.dateData.endTime, endTime: this.dateData.endTime,
sort: this.sort, sort: this.sort,
index: undefined, index: undefined,
factory: undefined factory: undefined
// timeDim: obj.mode
}).then((res) => { }).then((res) => {
console.log(res); console.log('res==============================',res);
this.monthData= res.data.month this.monthData= res.data.month
this.ytdData = res.data.ytd this.ytdData = res.data.ytd

View File

@@ -87,11 +87,14 @@ export default {
// 如果没有 X 轴数据,则返回空数组 // 如果没有 X 轴数据,则返回空数组
if (xAxisKeys.length === 0) { if (xAxisKeys.length === 0) {
return []; return {};
}
let obj = {
unit:'万元',
series:[]
} }
// 遍历配置项,生成 series // 遍历配置项,生成 series
return Object.keys(this.chartConfig).map(key => { obj.series = Object.keys(this.chartConfig).map(key => {
const config = this.chartConfig[key]; const config = this.chartConfig[key];
// 确保数据顺序和 X 轴一致 // 确保数据顺序和 X 轴一致
const dataValues = xAxisKeys.map(date => lineData[key] ? lineData[key].real[date] : 0); const dataValues = xAxisKeys.map(date => lineData[key] ? lineData[key].real[date] : 0);
@@ -114,6 +117,7 @@ export default {
data: dataValues data: dataValues
}; };
}); });
return obj;
} }
}, },
methods: {} methods: {}

View File

@@ -11,8 +11,8 @@
@mouseleave.native="autoScroll(false)" v-loading="isLoading" @mouseleave.native="autoScroll(false)" v-loading="isLoading"
:header-cell-style="{ background: 'rgba(218, 226, 237, 1)', color: 'rgba(0, 0, 0, .6)',padding:'3px 2px'}" :row-style="setRowStyle" :header-cell-style="{ background: 'rgba(218, 226, 237, 1)', color: 'rgba(0, 0, 0, .6)',padding:'3px 2px'}" :row-style="setRowStyle"
:data="renderData" border style="width: 100%; background: transparent"> :data="renderData" border style="width: 100%; background: transparent">
<el-table-column v-if="page && limit && showIndex" prop="_pageIndex" label="序号" :width="70" align="center" /> <el-table-column v-if="page && limit && showIndex" prop="_pageIndex" label="序号" :width="60" align="center" />
<el-table-column v-for="item in renderTableHeadList" :key="item.prop" :show-overflow-tooltip="showOverflow" <el-table-column v-for="item in renderTableHeadList" :key="item.prop" :show-overflow-tooltip="showOverflow" :width='item.width || ""'
v-bind="item"> v-bind="item">
<template slot-scope="scope"> <template slot-scope="scope">
@@ -39,7 +39,7 @@ export default {
maxHeight: { maxHeight: {
type: [Number, String], // 支持数字如300或字符串如'300px' type: [Number, String], // 支持数字如300或字符串如'300px'
required: false, required: false,
default: 200 // 原固定值,作为默认 fallback default: 200 // 原固定值,作为默认 fallback
}, },
tableData: { tableData: {
type: Array, type: Array,

View File

@@ -90,7 +90,7 @@
</el-upload> </el-upload>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button> <el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button> <el-button @click="cancelBtn"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
</Container> </Container>
@@ -512,6 +512,10 @@ export default {
this.$message.error('上传失败!') this.$message.error('上传失败!')
} }
}, },
cancelBtn() {
this.upload.open = false
this.$refs.upload.clearFiles();
}
} }
} }
</script> </script>

View File

@@ -57,10 +57,10 @@ export default {
activeButton: 0, activeButton: 0,
// 定义按钮与 line 数据中 key 的映射关系 // 定义按钮与 line 数据中 key 的映射关系
buttonToDataKey: [ buttonToDataKey: [
'单价', {name:'单价',unit:'元/㎡'},
'净价', {name:'净价',unit:'元/㎡'},
'销量', {name:'销量',unit:'万㎡'},
'双镀销量' // 注意:数据中的 key 是“双镀面板”,按钮显示的是“双镀产品” {name:'双镀销量',unit:'万㎡'}
] ]
}; };
}, },
@@ -69,7 +69,7 @@ export default {
xAxisData() { xAxisData() {
const lineData = this.line || {}; const lineData = this.line || {};
// 获取当前激活按钮对应的数据 // 获取当前激活按钮对应的数据
const currentDataKey = this.buttonToDataKey[this.activeButton]; const currentDataKey = this.buttonToDataKey[this.activeButton].name;
const currentIndicatorData = lineData[currentDataKey]; const currentIndicatorData = lineData[currentDataKey];
// 使用 'target' 的键作为 x 轴,如果 'target' 不存在,则使用 'real' 的键 // 使用 'target' 的键作为 x 轴,如果 'target' 不存在,则使用 'real' 的键
@@ -83,19 +83,20 @@ export default {
// 根据激活按钮动态返回对应 series 数据 // 根据激活按钮动态返回对应 series 数据
currentSeries() { currentSeries() {
const lineData = this.line || {}; const lineData = this.line || {};
const currentDataKey = this.buttonToDataKey[this.activeButton]; const currentDataKey = this.buttonToDataKey[this.activeButton].name;
const chartData = lineData[currentDataKey]; const chartData = lineData[currentDataKey];
if (!chartData) { if (!chartData) {
return []; return {};
} }
// 提取目标和实际数据的值,并确保顺序与 X 轴一致 // 提取目标和实际数据的值,并确保顺序与 X 轴一致
const xAxisKeys = this.xAxisData; const xAxisKeys = this.xAxisData;
const targetDataValues = xAxisKeys.map(date => chartData.target ? chartData.target[date] : 0); const targetDataValues = xAxisKeys.map(date => chartData.target ? chartData.target[date] : 0);
const realDataValues = xAxisKeys.map(date => chartData.real ? chartData.real[date] : 0); const realDataValues = xAxisKeys.map(date => chartData.real ? chartData.real[date] : 0);
let obj = {
return [ unit:this.buttonToDataKey[this.activeButton].unit,
series:[
{ {
name: '预算', name: '预算',
type: 'line', type: 'line',
@@ -136,7 +137,8 @@ export default {
}, },
data: realDataValues data: realDataValues
} }
]; ]}
return obj;
} }
} }
}; };

View File

@@ -6,8 +6,8 @@
<coreBottomLeftItem :dateData="dateData" :purchase="purchase"> <coreBottomLeftItem :dateData="dateData" :purchase="purchase">
</coreBottomLeftItem> </coreBottomLeftItem>
<div class="content-right" style="background: #F9FCFF;padding: 15px 12px;"> <div class="content-right" style="background: #F9FCFF;padding: 15px 12px;">
<base-table style="height: 180px;width: 260px;" :page="1" :limit="10" :show-index="true" :beilv="1" <base-table style="height: 221px;width: 260px;" :page="1" :limit="10" :show-index="true" :beilv="1"
:tableConfig="tableProps" :table-data="maintenanceTasks" /> :tableConfig="tableProps" :table-data="maintenanceTasks" :maxHeight='220'/>
</div> </div>
</div> </div>
</Container> </Container>
@@ -43,20 +43,13 @@ export default {
maintenanceTasks: [ maintenanceTasks: [
{ id: 1, name: '纯碱', number: '1313,252', }, { id: 1, name: '纯碱', number: '1313,252', },
{ id: 2, name: '硅砂', number: '14,252', }, { id: 2, name: '硅砂', number: '14,252', },
{ id: 2, name: '白云石', number: '23,252', }, { id: 3, name: '白云石', number: '23,252', },
{ id: 2, name: '石灰石', number: '34,421', }, { id: 4, name: '石灰石', number: '34,421', },
{ id: 2, name: '氧化铝', number: '1,251.34', }, { id: 5, name: '氧化铝', number: '1,251.34', },
{ id: 2, name: '氢氧化铝', number: '14,252', }, { id: 6, name: '氢氧化铝', number: '14,252', }
// { id: 2, eqName: '螺杆挤出', taskName: '例行维护', },
// { id: 2, eqName: '螺杆挤出', taskName: '例行维护', },
// { id: 2, eqName: '螺杆挤出', taskName: '例行维护', },
// { id: 2, eqName: '螺杆挤出', taskName: '例行维护', },
// { id: 2, eqName: '螺杆挤出', taskName: '例行维护', },
], ],
tableProps: [ tableProps: [
// { prop: 'id', label: '序号', width: 50, align: 'center' },
{ prop: 'name', label: '物料', align: 'left' }, { prop: 'name', label: '物料', align: 'left' },
{ prop: 'number', label: '库存/吨', align: 'left' }, { prop: 'number', label: '库存/吨', align: 'left' },
] ]
@@ -102,7 +95,7 @@ export default {
return { return {
id: index + 1, // id 从 1 开始自增 id: index + 1, // id 从 1 开始自增
name: name, // 物料名称 name: name, // 物料名称
number: String(value) // 将数值转换为字符串,以匹配 "number" 字段 number: value ? String(value) : '-' // 将数值转换为字符串,以匹配 "number" 字段
}; };
}); });
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<div ref="cockpitEffChip" id="coreLineChart" style="height: 219px; width: 100%;"></div> <div ref="cockpitEffChip" id="coreLineChart" style="height: 184px; width: 100%;"></div>
</template> </template>
<script> <script>
@@ -11,8 +11,8 @@ export default {
// 接收父组件传递的 series 数据 // 接收父组件传递的 series 数据
props: { props: {
chartSeries: { chartSeries: {
type: Array, type: Object,
default: () => [] // 默认空数组,避免报错 default: () => {{}} // 默认空数组,避免报错
}, },
xAxisData: { xAxisData: {
type: Array, type: Array,
@@ -68,7 +68,6 @@ export default {
// 单独提取更新图表的方法,方便复用 // 单独提取更新图表的方法,方便复用
updateChart() { updateChart() {
if (!this.myChart) return; if (!this.myChart) return;
console.log('this.chartSeries', this.chartSeries,this.xAxisData);
const option = { const option = {
tooltip: { tooltip: {
@@ -78,7 +77,7 @@ export default {
label: { backgroundColor: '#6a7985' } label: { backgroundColor: '#6a7985' }
} }
}, },
grid: { top: 35, bottom: 3, right: 15, left: 10, containLabel: true}, grid: { top: 35, bottom: 3, right: 15, left: 15, containLabel: true},
xAxis: [ xAxis: [
{ {
type: 'category', type: 'category',
@@ -108,19 +107,14 @@ export default {
} }
], ],
yAxis: { yAxis: {
// type: 'value', name: this.chartSeries.unit,
name: '元/㎡',
// nameLocation:'center',
nameTextStyle: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 14, align: 'right' }, nameTextStyle: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 14, align: 'right' },
// min: () => 0,
// max: (value) => Math.ceil(value.max),
axisTick: { show: false }, axisTick: { show: false },
axisLabel: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 12 }, axisLabel: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 12 },
splitLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } }, splitLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
axisLine: { show: true, lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } } axisLine: { show: true, lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } }
}, },
series: this.chartSeries // 使用父组件传递的 series 数据 series: this.chartSeries.series // 使用父组件传递的 series 数据
}; };
this.myChart.setOption(option, true); // 第二个参数 true 表示替换现有配置 this.myChart.setOption(option, true); // 第二个参数 true 表示替换现有配置

View File

@@ -24,7 +24,7 @@
<div class="right"> <div class="right">
<!-- 环比额计算差值并动态绑定颜色 --> <!-- 环比额计算差值并动态绑定颜色 -->
<div class="number" :style="{ color: getColor(item.currentValue, item.targetValue) }"> <div class="number" :style="{ color: getColor(item.currentValue, item.targetValue) }">
{{ item.hbe }} {{ item.thbe }}
</div> </div>
<div class="title">环比额</div> <div class="title">环比额</div>
</div> </div>
@@ -101,12 +101,12 @@ export default {
// 遍历映射关系,转换数据 // 遍历映射关系,转换数据
return costMapping.map(mappingItem => { return costMapping.map(mappingItem => {
// 获取对应费用类型的数据,若不存在则使用默认值 // 获取对应费用类型的数据,若不存在则使用默认值
const costData = rawData[mappingItem.key] || { last: 0, this: 0, hbe: 0 }; const costData = rawData[mappingItem.key] || { last: 0, this: 0, thbe: 0 };
return { return {
name: mappingItem.name, name: mappingItem.name,
path: mappingItem.path, path: mappingItem.path,
hbe: costData.hbe, thbe: costData.thbe,
targetValue: costData.last, // 上月值 targetValue: costData.last, // 上月值
currentValue: costData.this // 本月值 currentValue: costData.this // 本月值
}; };

View File

@@ -2,10 +2,10 @@
<div style="flex: 1"> <div style="flex: 1">
<!-- 传入点击切换的状态到Container组件 --> <!-- 传入点击切换的状态到Container组件 -->
<Container name="财务重点指标" nameTwo="费用重点指标" icon="cockpitItemIcon" size="topBasic" @switchTab="handleTabSwitch" @tabChange='tabChange'> <Container name="财务重点指标" nameTwo="费用重点指标" icon="cockpitItemIcon" size="topBasic" @switchTab="handleTabSwitch" @tabChange='tabChange'>
<div class="bottom-left-content" style="display: flex;gap: 9px;padding: 14px 16px;flex-direction: column;"> <div class="bottom-left-content" style="display: flex;gap: 0px;padding: 14px 16px;flex-direction: column;">
<!-- 根据activeTab状态切换显示采购/存货内容 --> <!-- 根据activeTab状态切换显示采购/存货内容 -->
<template v-if="activeTab === 'purchase'"> <template v-if="activeTab === 'purchase'">
<!-- 采购重点指标应的内容 --> <!-- 财务重点指标应的内容 -->
<coreBottomLeftItem :dateData="dateData" :finance="financeData"></coreBottomLeftItem> <coreBottomLeftItem :dateData="dateData" :finance="financeData"></coreBottomLeftItem>
<div class="bottom" <div class="bottom"
style="display: flex; width: 100%;margin-top: 8px;background-color: rgba(249, 252, 255, 1);"> style="display: flex; width: 100%;margin-top: 8px;background-color: rgba(249, 252, 255, 1);">
@@ -13,10 +13,10 @@
</div> </div>
</template> </template>
<template v-else-if="activeTab === 'inventory'"> <template v-else-if="activeTab === 'inventory'">
<!-- 存货重点指标对应的内容 --> <!-- 费用重点指标对应的内容 -->
<costItem :dateData="dateData" :cost="costData" :currentTap='currentTap'></costItem> <costItem :dateData="dateData" :cost="costData" :currentTap='currentTap'></costItem>
<div class="bottom" <div class="bottom"
style="display: flex; width: 100%;margin-top: 8px;background-color: rgba(249, 252, 255, 1);"> style="display: flex; width: 100%;margin-top: 4px;background-color: rgba(249, 252, 255, 1);">
<CostsBottomBar :line="cost.line" :dateData="dateData"> <CostsBottomBar :line="cost.line" :dateData="dateData">
</CostsBottomBar> </CostsBottomBar>
</div> </div>

View File

@@ -27,11 +27,21 @@
<div class="item-button" :class="{ active: activeButton === 3 }" @click="activeButton = 3"> <div class="item-button" :class="{ active: activeButton === 3 }" @click="activeButton = 3">
毛利率 毛利率
</div> </div>
<div class="button-line lineFour" v-if="activeButton !== 3 && activeButton !== 4"></div>
<div class="item-button" :class="{ active: activeButton === 4 }" @click="activeButton = 4">
应收账款
</div>
<div class="button-line lineFive" v-if="activeButton !== 4 && activeButton !== 5"></div>
<div class="item-button" :class="{ active: activeButton === 5 }" @click="activeButton = 5">
存货
</div>
</div> </div>
</div> </div>
<div class="lineBottom" style="height: 210px; width: 100%"> <div class="lineBottom" style="height: 184px; width: 100%">
<!-- 传递当前选中的 series 数据和 xAxis 数据给子组件 --> <!-- 传递当前选中的 series 数据和 xAxis 数据给子组件 -->
<coreLineChart style="height: 210px; width: 680px" :chart-series="currentSeries" :x-axis-data="xAxisData" <coreLineChart style="height: 184px; width: 680px" :chart-series="currentSeries" :x-axis-data="xAxisData"
:dateData="dateData" /> :dateData="dateData" />
</div> </div>
</div> </div>
@@ -59,10 +69,12 @@ export default {
activeButton: 0, // 初始激活第一个按钮索引0 activeButton: 0, // 初始激活第一个按钮索引0
// 定义按钮与 line 数据中 key 的映射关系 // 定义按钮与 line 数据中 key 的映射关系
buttonToDataKey: [ buttonToDataKey: [
'营业收入', {name:'营业收入',unit:'万元'},
'经营性利润', // 注意:数据中的 key 是“经营收入”,按钮显示的是“经营性利润” {name:'经营性利润',unit:'万元'},
'利润总额', {name:'利润总额',unit:'万元'},
'毛利率' {name:'毛利率',unit:'%'},
{name:'应收账款',unit:'万元'},
{name:'存货',unit:'万元'}
] ]
}; };
}, },
@@ -70,20 +82,19 @@ export default {
// 根据当前激活的按钮,动态生成对应的 series 数据 // 根据当前激活的按钮,动态生成对应的 series 数据
currentSeries() { currentSeries() {
const dataKey = this.buttonToDataKey[this.activeButton]; const dataKey = this.buttonToDataKey[this.activeButton].name;
const chartData = this.line[dataKey]; const chartData = this.line[dataKey];
console.log('this.line[dataKey', this.buttonToDataKey[this.activeButton]);
if (!chartData) { if (!chartData) {
return []; return {};
} }
// 提取目标和实际数据的值 // 提取目标和实际数据的值
const targetDataValues = Object.values(chartData.target || {}); const targetDataValues = Object.values(chartData.target || {});
const realDataValues = Object.values(chartData.real || {}); const realDataValues = Object.values(chartData.real || {});
console.log('realDataValues', realDataValues); let obj = {
unit: this.buttonToDataKey[this.activeButton].unit,
return [ series:[
{ {
name: '预算', name: '预算',
type: 'line', type: 'line',
@@ -116,11 +127,12 @@ export default {
}, },
data: realDataValues data: realDataValues
} }
]; ]}
return obj;
}, },
// 提取 x 轴数据(日期) // 提取 x 轴数据(日期)
xAxisData() { xAxisData() {
const dataKey = this.buttonToDataKey[this.activeButton]; const dataKey = this.buttonToDataKey[this.activeButton].name;
const chartData = this.line[dataKey]; const chartData = this.line[dataKey];
// 使用 'target' 的键作为 x 轴,如果 'target' 不存在,则使用 'real' 的键 // 使用 'target' 的键作为 x 轴,如果 'target' 不存在,则使用 'real' 的键
if (chartData && chartData.target) { if (chartData && chartData.target) {
@@ -205,7 +217,7 @@ export default {
display: flex; display: flex;
position: relative; position: relative;
gap: 2px; gap: 2px;
width: 252px; width: 350px;
align-items: center; align-items: center;
height: 24px; height: 24px;
background: #ecf4fe; background: #ecf4fe;
@@ -219,18 +231,27 @@ export default {
} }
.lineOne { .lineOne {
top: 5px; top: 6px;
left: 59px; left: 59px;
} }
.lineTwo { .lineTwo {
top: 5px; top: 6px;
left: 134px; left: 131px;
} }
.lineThree { .lineThree {
top: 5px; top: 6px;
left: 193px; left: 190px;
}
.lineFour {
top: 6px;
left: 238px;
}
.lineFive {
top: 6px;
left: 302px;
} }
.item-button { .item-button {

View File

@@ -1,7 +1,7 @@
<template> <template>
<!-- 显示累计值并绑定颜色类 --> <!-- 显示累计值并绑定颜色类 -->
<div class="accumulated-value" :class="injectData.status"> <div class="accumulated-value" :class="injectData.status">
{{ injectData.accumulated }} <!-- 显示累计数据 --> {{ injectData.total }} <!-- 显示累计数据 -->
</div> </div>
</template> </template>

View File

@@ -15,10 +15,6 @@ export default {
lineData: { lineData: {
type: Object, type: Object,
default: () => ({}), default: () => ({}),
},
xData: {
type: Array,
default: () => []
} }
}, },
mounted() { mounted() {
@@ -32,7 +28,6 @@ export default {
// 深度监听数据变化,仅更新图表配置(不销毁实例) // 深度监听数据变化,仅更新图表配置(不销毁实例)
lineData: { lineData: {
handler() { handler() {
console.log(this.lineData,'lineData');
this.updateChart(); this.updateChart();
}, },
deep: true, deep: true,
@@ -52,8 +47,12 @@ export default {
} }
this.myChart = echarts.init(chartDom); this.myChart = echarts.init(chartDom);
const entries = Object.entries(this.lineData);
entries.sort((item1, item2) => item2[1] - item1[1]);
const sortedObj = Object.fromEntries(entries);
let xData = Object.keys(sortedObj);
let yData = Object.values(sortedObj);
console.log('linedaata',this.lineData)
const option = { const option = {
tooltip: { tooltip: {
@@ -86,7 +85,7 @@ export default {
interval: 0, interval: 0,
padding: [5, 0, 0, 0] padding: [5, 0, 0, 0]
}, },
data:this.xData data:xData
} }
], ],
yAxis: [ yAxis: [
@@ -112,7 +111,31 @@ export default {
splitNumber: 4 splitNumber: 4
}, },
], ],
series: [] series: [
{
name: '实际',
type: 'bar',
yAxisIndex: 0,
barWidth: 40,
label: {
show: true,
position: 'top'
},
itemStyle: {
color:{
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(130, 204, 255, 1)' },
{ offset: 1, color: 'rgba(75, 157, 255, 1)' }
]
},
borderRadius: [4, 4, 0, 0],
borderWidth: 0
},
data: yData
}
]
}; };
option && this.myChart.setOption(option); option && this.myChart.setOption(option);

View File

@@ -77,7 +77,7 @@ font-style: normal;">指标详情</div>
</el-upload> </el-upload>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button> <el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button> <el-button @click="cancelBtn"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
</Container> </Container>
@@ -387,6 +387,10 @@ export default {
console.error('文件上传出错:', error) console.error('文件上传出错:', error)
this.$message.error('上传失败!') this.$message.error('上传失败!')
} }
},
cancelBtn(){
this.upload.open = false
this.$refs.upload.clearFiles();
} }
} }
} }

View File

@@ -17,10 +17,10 @@
<div class="bottom" style="background-color: rgba(249, 252, 255, 1);"> <div class="bottom" style="background-color: rgba(249, 252, 255, 1);">
<div class="bottom" style="margin-top: 8px;background-color: rgba(249, 252, 255, 1);"> <div class="bottom" style="margin-top: 8px;background-color: rgba(249, 252, 255, 1);">
<div style='text-align: center;margin: 5px;font-size: 18px;font-weight: 400;color: #000;'>1200t/d</div> <div style='text-align: center;margin: 5px;font-size: 18px;font-weight: 400;color: #000;'>1200t/d</div>
<heatBar :lineData="heatData['1200t']" :xData="['桐城','洛阳','江苏','秦皇岛']" :dateData="dateData" /> <heatBar :lineData="heatData['1200t']"/>
</div> </div>
<div style='text-align: center;margin: 5px;font-size: 18px;font-weight: 400;color: #000;'>650t/d</div> <div style='text-align: center;margin: 5px;font-size: 18px;font-weight: 400;color: #000;'>650t/d</div>
<heatBar :lineData="heatData['650t']" :xData="['宜兴','自贡','漳州']" :dateData="dateData" /> <heatBar :lineData="heatData['650t']"/>
</div> </div>
</template> </template>
</div> </div>
@@ -51,10 +51,6 @@ export default {
type: Object, type: Object,
default: () => { } // 默认空数组,避免报错 default: () => { } // 默认空数组,避免报错
}, },
heat: {
type: Object,
default: () => { }
}
}, },
data() { data() {
return { return {

View File

@@ -15,7 +15,7 @@
<span class="legend-text">未完成</span> <span class="legend-text">未完成</span>
</div> </div>
</div> </div>
<base-table style="height: 180px;" :page="1" :limit="10" :show-index="true" :beilv="1" <base-table style="height: 204px;" :page="1" :limit="10" :show-index="true" :beilv="1"
:tableConfig="tableProps" :table-data="tableData" /> :tableConfig="tableProps" :table-data="tableData" />
</div> </div>
</div> </div>
@@ -33,18 +33,18 @@ export default {
components: { Container, baseTable }, components: { Container, baseTable },
props: { props: {
importantWork: { importantWork: {
type: Object, type: Array,
default: () => ({}) default: () => ([])
} }
}, },
data() { data() {
return { return {
tableData: [], tableData: [],
tableProps: [ tableProps: [
{ prop: 'name', label: '攻坚指标', align: 'center' }, { prop: 'index', label: '攻坚指标', align: 'center',width:150 },
{ prop: 'target', label: '攻坚预算', align: 'center' }, { prop: 'target', label: '攻坚预算', align: 'center' },
{ prop: 'monthlyActual', label: '当月实际', align: 'center' }, { prop: 'real', label: '当月实际', align: 'center' },
{ prop: 'accumulated', label: '累计', align: 'center', subcomponent: finishDiv }, { prop: 'total', label: '累计', align: 'center', subcomponent: finishDiv },
] ]
} }
}, },
@@ -59,33 +59,13 @@ export default {
}, },
methods: { methods: {
transformData(rawData) { transformData(rawData) {
if (!rawData || typeof rawData !== 'object') return []; return rawData.map((item, index) =>{
const mapping = [
{ key: 'jyxxjl', name: '经营现金流', unit: '万元' },
{ key: 'yszk', name: '应收账款', unit: '万元' },
{ key: 'ch', name: '存货', unit: '万元' },
{ key: 'yysr', name: '营业收入', unit: '万元' },
{ key: 'snysysk', name: '三年以上应收款', unit: '万元' },
{ key: 'dzje', name: '非经营性资产处置到账金额', unit: '万元' },
{ key: 'yfjftr', name: '研发经费投入', unit: '万元' },
{ key: 'yfjftrqd', name: '研发经费投入强度', unit: '%' }
];
return mapping.map((item, index) => {
const data = rawData[item.key] || { monValue: 0, real: 0, target: 0 };
const accumulated = data.real || 0;
const target = data.target || 0;
return { return {
...item,
id: index + 1, id: index + 1,
name: item.name + '/' + item.unit, status: (item.real > 0 && item.target > 0 && item.real / item.target >= 1 || item.real >= item.target) ? 'done' : 'pending'
target: target,
monthlyActual: data.monValue,
accumulated: accumulated,
status: accumulated > 0 && target > 0 && accumulated / target >= 1 ? 'done' : 'pending'
}; };
}); })
} }
} }
} }

View File

@@ -1,18 +1,18 @@
<template> <template>
<div class="coreItem"> <div class="coreItem">
<!-- 单独渲染第一个item --> <!-- 单独渲染第一个item -->
<div class="item" v-if="itemList.length > 0"> <div class="item" v-if="itemList.length > 0" v-for="(item, index) in itemList">
<div class="unit">{{ itemList[0].unit }}</div> <div class="unit">{{ item.unit }}</div>
<div class="item-content"> <div class="item-content">
<div class="content-wrapper"> <div class="content-wrapper">
<div class="left"> <div class="left">
<div class="number">{{ itemList[0].targetValue }}</div> <div class="number">{{ item.targetValue }}</div>
<div class="title">预算值</div> <div class="title">预算值</div>
</div> </div>
<div class="line"></div> <div class="line"></div>
<div class="right"> <div class="right">
<div class="number" :style="{ color: getColor(itemList[0].currentValue, itemList[0].targetValue) }"> <div class="number" :style="{ color: getColor(item.currentValue, item.targetValue) }">
{{ itemList[0].currentValue }} {{ item.currentValue }}
</div> </div>
<div class="title">实际值</div> <div class="title">实际值</div>
</div> </div>
@@ -23,7 +23,7 @@
<!-- 进度条颜色和宽度动态绑定 --> <!-- 进度条颜色和宽度动态绑定 -->
<div class="progress-bar" :style="{ <div class="progress-bar" :style="{
width: itemList[0].progress + '%', width: itemList[0].progress + '%',
background: getColor(itemList[0].currentValue, itemList[0].targetValue) background: getColor(item.currentValue, item.targetValue)
}"></div> }"></div>
</div> </div>
</div> </div>
@@ -32,67 +32,9 @@
<div class="progress-percent">完成率</div> <div class="progress-percent">完成率</div>
<!-- 百分比颜色动态绑定 --> <!-- 百分比颜色动态绑定 -->
<div class="progress-percent" :style="{ <div class="progress-percent" :style="{
color: getColor(itemList[0].currentValue, itemList[0].targetValue) color: getColor(item.currentValue, item.targetValue)
}"> }">
{{ itemList[0].progress }}% {{ item.progress }}%
</div>
</div>
</div>
</div>
<!-- 循环渲染剩余的item从索引1开始 -->
<div class="item groupData" style="display: flex;padding: 0;" v-for="(item, index) in itemList.slice(1)"
:key="index">
<!-- 左侧预算值/实际值部分不变 -->
<div class="left" style="display: flex;align-items: start;gap: 4px;padding: 12px 0 0 12px;">
<div class="groupName">{{ item.unit }}</div>
<div class="left-target">
<div class="number">{{ item.targetValue }}</div>
<div class="title">预算值</div>
</div>
<div class="left-real">
<div class="number" :style="{ color: getColor(item.currentValue, item.targetValue) }">
{{ item.currentValue }}
</div>
<div class="title">实际值</div>
</div>
</div>
<div class="cityLine"></div>
<div class="right">
<!-- 顶部完成率部分不变 -->
<div class="groupName" :class="{
'bg-default': item.currentValue < item.targetValue,
'bg-green': item.currentValue >= item.targetValue
}" style="font-size: 12px;display: flex;align-items: center;justify-content: flex-end;">
<div class="title">完成率</div>
<div class="yield" style="font-size: 22px;margin-bottom: 4px;">
{{ item.progress }}
</div>
<div class="unit">%</div>
</div>
<!-- 动态渲染城市进度循环 item.cities -->
<div class="right-city" v-for="(city, cityIdx) in item.cities" :key="cityIdx"
:style="{ marginTop: cityIdx > 0 ? '2px' : '0' }" @click="getTableData(city.num)" style="cursor: pointer;">
<div class="city">{{ city.name }}</div> <!-- 动态城市名 -->
<div class="city-progress-group">
<div class="city-progress-container">
<!-- 动态城市进度条颜色按城市进度判断 -->
<div class="city-progress-bar" :style="{
width: city.progress + '%',
background: getColor(city.completed, city.total) // 用城市已完成/总数判断颜色
}"></div>
</div>
</div>
<div class="city-progress-yield" style="display: flex;justify-content: space-between;">
<!-- 动态比值已完成/总数 -->
<div class="numerator" :style="{ color: getColor(city.completed, city.total) }">
{{ city.completed }}/{{ city.total }}
</div>
<!-- 动态城市完成率 -->
<div class="city-yield" :style="{ color: getColor(city.completed, city.total) }">
{{ city.progress }}%
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -108,60 +50,7 @@ export default {
data() { data() {
return { return {
progress: 90, // 进度值基础参数 progress: 90, // 进度值基础参数
itemList: [ itemList: []
// {
// unit: "总进度",
// targetValue: 16,
// currentValue: 14.5,
// progress: 90,
// cities: [] // 总进度无需城市数据,留空
// },
// {
// unit: "一组",
// targetValue: 16,
// currentValue: 17,
// progress: 106,
// cities: [
// { name: "桐城", completed: 12, total: 13, progress: 92 },
// { name: "自贡", completed: 15, total: 16, progress: 93 } // 新增城市示例
// ]
// },
// {
// unit: "二组",
// targetValue: 16,
// currentValue: 16,
// progress: 100,
// cities: [
// { name: "蚌埠", completed: 10, total: 12, progress: 83 },
// { name: "合肥", completed: 8, total: 10, progress: 80 }
// ]
// },
// // 其他组同理,按需添加 cities 数据
// {
// unit: "三组",
// targetValue: 16,
// currentValue: 15.2,
// progress: 85,
// cities: [{ name: "宜兴", completed: 9, total: 11, progress: 81 }]
// },
// {
// unit: "四组",
// targetValue: 16,
// currentValue: 18,
// progress: 112,
// cities: [
// { name: "漳州", completed: 14, total: 15, progress: 93 },
// { name: "洛阳", completed: 12, total: 14, progress: 85 }
// ]
// },
// {
// unit: "五组",
// targetValue: 16,
// currentValue: 14,
// progress: 80,
// cities: [{ name: "桐城", completed: 7, total: 9, progress: 77 }]
// }
]
}; };
}, },
watch: { watch: {
@@ -180,56 +69,36 @@ export default {
targetValue: data.totalProgress.target, targetValue: data.totalProgress.target,
currentValue: data.totalProgress.real, currentValue: data.totalProgress.real,
progress: data.totalProgress.rate, progress: data.totalProgress.rate,
cities: [] // 总进度无需城市数据,留空
}, },
{ {
unit: "一组", unit: "一组",
targetValue: data.group1.target, targetValue: data.group1.target,
currentValue: data.group1.real, currentValue: data.group1.real,
progress: data.group1.rate, progress: data.group1.rate
cities: [
{ name: "桐城", completed: data[2].real, total: data[2].target, progress: data[2].rate,num:2 },
{ name: "自贡", completed: data[3].real, total: data[3].target, progress: data[3].rate, num: 3 } // 新增城市示例
]
}, },
{ {
unit: "二组", unit: "二组",
targetValue: data.group2.target, targetValue: data.group2.target,
currentValue: data.group2.real, currentValue: data.group2.real,
progress: data.group2.rate, progress: data.group2.rate
cities: [
{ name: "蚌埠", completed: data[4].real, total: data[4].target, progress: data[4].rate, num: 4 },
{ name: "合肥", completed: data[5].real, total: data[5].target, progress: data[5].rate, num: 5 }
]
}, },
// 其他组同理,按需添加 cities 数据
{ {
unit: "三组", unit: "三组",
targetValue: data.group3.target, targetValue: data.group3.target,
currentValue: data.group3.real, currentValue: data.group3.real,
progress: data.group3.rate, progress: data.group3.rate
cities: [{ name: "江苏凯盛", completed: data[6].real, total: data[6].target, progress: data[6].rate, num: 6 },
{ name: "宜兴", completed: data[7].real, total: data[7].target, progress: data[7].rate, num: 7 }
]
}, },
{ {
unit: "四组", unit: "四组",
targetValue: data.group4.target, targetValue: data.group4.target,
currentValue: data.group4.real, currentValue: data.group4.real,
progress: data.group4.rate, progress: data.group4.rate
cities: [
{ name: "漳州", completed: data[8].real, total: data[8].target, progress: data[8].rate, num: 8 },
{ name: "洛阳", completed: data[9].real, total: data[9].target, progress: data[9].rate, num: 9 }
]
}, },
{ {
unit: "五组", unit: "五组",
targetValue: data.group5.target, targetValue: data.group5.target,
currentValue: data.group5.real, currentValue: data.group5.real,
progress: data.group5.rate, progress: data.group5.rate
cities: [{ name: "秦皇岛", completed: data[10].real, total: data[10].target, progress: data[10].rate, num: 10 },
// { name: "秦皇岛", completed: 7, total: 9, progress: 77 }
]
} }
] ]
}, },
@@ -240,7 +109,6 @@ export default {
: "rgba(249, 164, 74, 1)"; : "rgba(249, 164, 74, 1)";
}, },
getTableData(data) { getTableData(data) {
console.log(data, 'data');
this.$emit('handleShowTable',data) this.$emit('handleShowTable',data)
} }
@@ -257,11 +125,12 @@ export default {
.coreItem { .coreItem {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between;
gap: 8px; gap: 8px;
} }
.item { .item {
width: 220px; width: 227px;
height: 122px; height: 122px;
background: #f9fcff; background: #f9fcff;
padding: 12px; padding: 12px;

View File

@@ -19,7 +19,7 @@ import * as echarts from 'echarts';
export default { export default {
name: 'Container', name: 'Container',
props: ["chartData",'dateData'], props: ["chartData",'dateData','unit'],
components: {}, components: {},
data() { data() {
return { return {
@@ -131,7 +131,7 @@ export default {
], ],
yAxis: { yAxis: {
type: 'value', type: 'value',
name: '元/㎡', name: this.unit,
// nameLocation:'center', // nameLocation:'center',
nameTextStyle: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 14, align: 'right' }, nameTextStyle: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 14, align: 'right' },
min: 0, min: 0,

View File

@@ -14,18 +14,28 @@
<div class="button-line lineFour" v-if="activeButton !== 3 && activeButton !== 4"></div> <div class="button-line lineFour" v-if="activeButton !== 3 && activeButton !== 4"></div>
<div class="item-button" style="width: 75px;" :class="{ active: activeButton === 4 }" @click="activeButton = 4"> <div class="item-button" style="width: 75px;" :class="{ active: activeButton === 4 }" @click="activeButton = 4">
投入产出率</div> 投入产出率</div>
<div class="button-line lineFive" v-if="activeButton !== 4 && activeButton !== 5"></div>
<div class="item-button" style="width: 45px;" :class="{ active: activeButton === 5 }" @click="activeButton = 5">
折旧</div>
</div> </div>
</div> </div>
<div class="lineBottom" style="height: 219px; width: 100%" v-if="isLineDataReady"> <div class="lineBottom" style="height: 219px; width: 100%" v-if="isLineDataReady">
<!-- 核心改动动态传递数据给子组件 --> <!-- 核心改动动态传递数据给子组件 -->
<coreLineChart style="height: 219px; width: 100%" :chart-data="selectedChartData" :dateData="dateData" /> <coreLineChart style="height: 219px; width: 100%" :chart-data="selectedChartData" :unit='unit' :dateData="dateData" />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import coreLineChart from './productBar.vue'; import coreLineChart from './productBar.vue';
const dataKeyMap = [
{name:'制造成本',unit:'元/㎡'},
{name:'原片成本',unit:'元/㎡'},
{name:'加工成本',unit:'元/㎡'},
{name:'原片成品率',unit:'%'},
{name:'投入产出率',unit:'%'},
{name:'折旧',unit:'万元'}
];
export default { export default {
name: "Container", name: "Container",
components: { coreLineChart }, components: { coreLineChart },
@@ -33,6 +43,7 @@ export default {
data() { data() {
return { return {
activeButton: 0, // 初始激活第一个按钮索引0 activeButton: 0, // 初始激活第一个按钮索引0
dataKeyMap
}; };
}, },
computed: { computed: {
@@ -42,22 +53,14 @@ export default {
}, },
// 核心改动计算属性根据activeButton动态返回选中的数据 // 核心改动计算属性根据activeButton动态返回选中的数据
selectedChartData() { selectedChartData() {
// 定义按钮索引与lineData中key的映射关系
const dataKeyMap = [
'制造成本',
'原片成本',
'加工成本',
'原片成品率',
'投入产出率'
];
// 根据当前激活的按钮索引获取对应的数据key // 根据当前激活的按钮索引获取对应的数据key
const selectedKey = dataKeyMap[this.activeButton]; const selectedKey = this.dataKeyMap[this.activeButton].name;
console.log(this.lineData[selectedKey]);
// 从lineData中获取对应的数据如果不存在则返回一个空对象以防止报错 // 从lineData中获取对应的数据如果不存在则返回一个空对象以防止报错
return this.lineData ? this.lineData[selectedKey] || {} : {}; return this.lineData ? this.lineData[selectedKey] || {} : {};
},
unit() {
return this.dataKeyMap[this.activeButton].unit;
} }
}, },
methods: {}, methods: {},
@@ -73,7 +76,7 @@ export default {
.barTop { .barTop {
display: flex; display: flex;
gap: 40px; gap: 20px;
.title { .title {
height: 18px; height: 18px;
@@ -91,7 +94,7 @@ export default {
display: flex; display: flex;
position: relative; position: relative;
gap: 2px; gap: 2px;
width: 327px; width: 356px;
align-items: center; align-items: center;
height: 24px; height: 24px;
background: #ecf4fe; background: #ecf4fe;
@@ -105,23 +108,27 @@ export default {
} }
.lineOne { .lineOne {
top: 5px; top: 6px;
left: 57px; left: 55px;
} }
.lineTwo { .lineTwo {
top: 5px; top: 6px;
left: 118px; left: 111px;
} }
.lineThree { .lineThree {
top: 5px; top: 6px;
left: 177px; left: 169px;
} }
.lineFour { .lineFour {
top: 5px; top: 6px;
left: 252px; left: 240px;
}
.lineFive {
top: 6px;
left: 314px;
} }
.item-button { .item-button {

View File

@@ -1,52 +1,96 @@
<template> <template>
<div class="coreItem"> <div>
<div class="item" @click="handleRoute(item.route)" v-for="(item, index) in itemList" :key="index"> <div class="coreItem">
<div class="name">{{ item.name }}</div> <div class="item" @click="handleRoute(item.route)" v-for="(item, index) in itemList" :key="index" v-if='index<4'>
<div class="item-content"> <div class="name">{{ item.name }}</div>
<div class="content-wrapper"> <div class="item-content">
<div class="left"> <div class="content-wrapper">
<div class="number" style="color: rgba(103, 103, 103, 0.79);">{{ item.targetValue }}</div> <div class="left">
<div class="title" style="color: rgba(134, 134, 135, 1);">目标值</div> <div class="number" style="color: rgba(103, 103, 103, 0.79);">{{ item.targetValue }}</div>
<div class="title" style="color: rgba(134, 134, 135, 1);">目标值</div>
</div>
<div class="line"></div>
<!-- 实际值根据 实际值目标值 动态绑定类名 -->
<div class="right">
<div class="number" :class="{
'number-exceed': item.currentValue >= item.targetValue,
'number-below': item.currentValue < item.targetValue
}">
{{ item.currentValue }}
</div>
<div class="title" style="color: rgba(134, 134, 135, 1);">实际值</div>
</div>
</div> </div>
<div class="line"></div> <div class="line"></div>
<!-- 实际值根据 实际值目标值 动态绑定类名 -->
<div class="right"> <!-- 进度条同步绑定类名 -->
<div class="number" :class="{ <div class="progress-group">
'number-exceed': item.currentValue >= item.targetValue, <div class="progress-container">
'number-below': item.currentValue < item.targetValue <div class="progress-bar" :style="{ width: item.progressWidth + '%' }" :class="{
}"> 'bar-exceed': item.currentValue >= item.targetValue,
{{ item.currentValue }} 'bar-below': item.currentValue < item.targetValue
}"></div>
</div> </div>
<div class="title" style="color: rgba(134, 134, 135, 1);">实际值</div>
</div> </div>
</div>
<div class="line"></div>
<!-- 进度条同步绑定类名 --> <!-- 完成率同步绑定类名 -->
<div class="progress-group"> <div class="yield" style="display: flex;justify-content: space-between;">
<div class="progress-container"> <div class="progress-percent" :class="{
<div class="progress-bar" :style="{ width: item.progressWidth + '%' }" :class="{ 'percent-exceed': item.currentValue >= item.targetValue,
'bar-exceed': item.currentValue >= item.targetValue, 'percent-below': item.currentValue < item.targetValue
'bar-below': item.currentValue < item.targetValue }">完成率</div>
}"></div> <div class="progress-percent" :class="{
</div> 'percent-exceed': item.currentValue >= item.targetValue,
</div> 'percent-below': item.currentValue < item.targetValue
}">
<!-- 完成率同步绑定类名 --> {{ item.progressDisplay }}
<div class="yield" style="display: flex;justify-content: space-between;"> </div>
<div class="progress-percent" :class="{
'percent-exceed': item.currentValue >= item.targetValue,
'percent-below': item.currentValue < item.targetValue
}">完成率</div>
<div class="progress-percent" :class="{
'percent-exceed': item.currentValue >= item.targetValue,
'percent-below': item.currentValue < item.targetValue
}">
{{ item.progressDisplay }}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="itemBottom">
<div class="item" v-for="(item, index) in itemList" :key="index" @click="handleRoute(item.route)" v-if='index>=4'>
<div class="unit">{{ item.name }}</div>
<div class="item-content">
<div class="content-wrapper">
<div class="left">
<div class="number">{{ item.targetValue }}</div>
<div class="title">目标值</div>
</div>
<div class="line"></div>
<!-- 实际值:根据与目标值的比较动态变色 -->
<div class="right">
<div class="number" :class="{
'exceed-target': item.currentValue > item.targetValue,
'below-target': item.currentValue < item.targetValue,
'equal-target': item.currentValue === item.targetValue
}">
{{ item.currentValue }}
</div>
<div class="title">实际值</div>
</div>
</div>
<!-- 进度条和百分比:同步变色逻辑 -->
<div class="progress-group">
<div class="progress-container">
<div class="progress-bar" :style="{ width: item.progress + '%' }" :class="{
'exceed-pro-target': item.currentValue > item.targetValue,
'below-pro-target': item.currentValue < item.targetValue,
'equal-pro-target': item.currentValue === item.targetValue
}"></div>
</div>
<div class="progress-percent" :class="{
'exceed-target': item.currentValue > item.targetValue,
'below-target': item.currentValue < item.targetValue,
'equal-target': item.currentValue === item.targetValue
}">
{{ item.progressDisplay }}
</div>
</div>
</div>
</div>
</div>
</div> </div>
</template> </template>
@@ -160,6 +204,18 @@ export default {
name: '毛利率·%', name: '毛利率·%',
route: '/grossMargin/grossMargin', route: '/grossMargin/grossMargin',
isPercentage: true // 需要加%符号 isPercentage: true // 需要加%符号
},
{
key: 'accountsReceivable',
name: '应收账款·万元',
route: '/accountsReceivable/accountsReceivableIndex',
isPercentage: false // 需要加%符号
},
{
key: 'inventory',
name: '存货·万元',
route: '/inventoryAnalysis/inventoryAnalysisIndex',
isPercentage: false // 需要加%符号
} }
]; ];
@@ -219,24 +275,152 @@ export default {
.coreItem { .coreItem {
display: flex; display: flex;
gap: 8px; gap: 8px;
// padding: 8px; // 避免边缘item hover阴影被截断 .item {
} width: 170px;
height: 168px;
background: #f9fcff;
padding: 12px 0px 0px 12px;
box-sizing: border-box;
cursor: pointer;
transition: all 0.3s ease;
.item { &:hover {
width: 170px; box-shadow: 0px 4px 12px 2px #B5CDE5;
height: 228px; transform: translateY(-2px);
}
.name {
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 18px;
color: #000000;
line-height: 18px;
letter-spacing: 1px;
text-align: left;
font-style: normal;
margin-bottom: 2px;
}
.item-content {
display: flex;
flex-direction: column;
justify-content: space-between;
height: calc(100% - 26px);
}
.content-wrapper {
display: flex;
flex-direction: column;
gap: 2px;
}
.line {
width: 149px;
height: 1px;
background: linear-gradient(to left, rgba(255, 0, 0, 0), #cbcbcb);
}
.left,
.right {
margin-top: 0px;
display: flex;
flex-direction: column;
gap: 2px;
width: 100%;
}
/* 实际值 - 基础样式(无颜色) */
.number {
height: 22px;
font-family: PingFangSC, PingFang SC;
font-weight: 600;
font-size: 24px;
line-height: 22px;
text-align: left;
font-style: normal;
}
/* 实际值 - 实际值≥目标值(绿色) */
.number-exceed {
color: rgba(54, 181, 138, 1) !important;
}
/* 实际值 - 实际值<目标值(黄色) */
.number-below {
color: rgba(249, 164, 74, 1) !important;
}
.title {
height: 14px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #868687;
line-height: 14px;
text-align: left;
font-style: normal;
}
.progress-group {
display: flex;
align-items: center;
gap: 8px;
margin-top: 2px;
}
.progress-container {
width: 138px;
height: 10px;
background: #ECEFF7;
border-radius: 8px;
overflow: hidden;
}
/* 进度条 - 基础样式(无颜色) */
.progress-bar {
height: 100%;
border-radius: 8px;
transition: width 0.5s ease;
}
/* 进度条 - 实际值≥目标值(绿色) */
.bar-exceed {
background: rgba(98, 213, 180, 1) !important;
opacity: 1 !important;
}
/* 进度条 - 实际值<目标值(黄色) */
.bar-below {
background: rgba(249, 164, 74, 1) !important;
opacity: 1 !important;
}
/* 百分比 - 基础样式(无颜色) */
.progress-percent {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
line-height: 1;
}
/* 百分比 - 实际值≥目标值(绿色) */
.percent-exceed {
color: rgba(54, 181, 138, 1) !important;
}
/* 百分比 - 实际值<目标值(黄色) */
.percent-below {
color: rgba(249, 164, 74, 1) !important;
}
.yield {
width: 138px;
margin-top: 3px;
}
}
}
.itemBottom {
display: flex;
gap: 8px;
margin-top: 5px;
.item {
width: 350px;
height: 90px;
background: #f9fcff; background: #f9fcff;
padding: 12px 0px 17px 12px; padding: 8px 8px 0px;
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer; // 提示可点击
transition: all 0.3s ease; transition: all 0.3s ease; // 动画过渡
&:hover { &:hover {
box-shadow: 0px 4px 12px 2px #B5CDE5; box-shadow: 0px 4px 12px 2px #B5CDE5;
transform: translateY(-2px); transform: translateY(-2px); // 轻微上浮增强交互感
} }
.name { .unit {
height: 18px; height: 18px;
font-family: PingFangSC, PingFang SC; font-family: PingFangSC, PingFang SC;
font-weight: 400; font-weight: 400;
@@ -246,57 +430,51 @@ export default {
letter-spacing: 1px; letter-spacing: 1px;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
margin-bottom: 2px;
} }
.item-content { .item-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
height: calc(100% - 26px); height: calc(100% - 29px);
} }
.content-wrapper { .content-wrapper {
display: flex; display: flex;
flex-direction: column; align-items: center;
gap: 10px; justify-content: space-around;
flex: 1;
} }
.line { .line {
width: 149px; width: 1px;
height: 1px; height: 46px;
background: linear-gradient(to left, rgba(255, 0, 0, 0), #cbcbcb); background: linear-gradient(to bottom, rgba(255, 0, 0, 0), #cbcbcb);
} }
.left, .left,
.right { .right {
margin-top: 11px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center;
align-items: center;
gap: 2px; gap: 2px;
width: 100%; flex: 1;
} }
/* 实际值 - 基础样式(无颜色) */
.number { .number {
height: 22px; height: 22px;
font-family: PingFangSC, PingFang SC; font-family: PingFangSC, PingFang SC;
font-weight: 600; font-weight: 600;
font-size: 24px; font-size: 24px;
color: rgba(103, 103, 103, 0.79);
/* 默认颜色(等于目标值时) */
line-height: 22px; line-height: 22px;
text-align: left; text-align: center;
font-style: normal; font-style: normal;
} }
/* 实际值 - 实际值≥目标值(绿色) */
.number-exceed {
color: rgba(54, 181, 138, 1) !important;
}
/* 实际值 - 实际值<目标值(黄色) */
.number-below {
color: rgba(249, 164, 74, 1) !important;
}
.title { .title {
height: 14px; height: 14px;
font-family: PingFangSC, PingFang SC; font-family: PingFangSC, PingFang SC;
@@ -304,7 +482,7 @@ export default {
font-size: 12px; font-size: 12px;
color: #868687; color: #868687;
line-height: 14px; line-height: 14px;
text-align: left; text-align: center;
font-style: normal; font-style: normal;
} }
@@ -312,57 +490,83 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
margin-top: 15px;
} }
.progress-container { .progress-container {
width: 138px; width: 280px;
height: 10px; height: 10px;
background: #ECEFF7; background: #ECEFF7;
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
} }
/* 进度条 - 基础样式(无颜色) */
.progress-bar { .progress-bar {
height: 100%; height: 100%;
background: rgba(98, 213, 180, 1);
/* 默认进度条颜色(等于目标值时) */
border-radius: 8px; border-radius: 8px;
transition: width 0.5s ease; opacity: 0.7;
transition: width 0.5s ease; // 进度条动画
} }
/* 进度条 - 实际值≥目标值(绿色) */
.bar-exceed {
background: rgba(98, 213, 180, 1) !important;
opacity: 1 !important;
}
/* 进度条 - 实际值<目标值(黄色) */
.bar-below {
background: rgba(249, 164, 74, 1) !important;
opacity: 1 !important;
}
/* 百分比 - 基础样式(无颜色) */
.progress-percent { .progress-percent {
font-family: PingFangSC, PingFang SC; font-family: PingFangSC, PingFang SC;
font-weight: 400; font-weight: 400;
font-size: 12px; font-size: 12px;
color: #868687;
/* 默认百分比颜色(等于目标值时) */
line-height: 1; line-height: 1;
} }
/* 百分比 - 实际值≥目标值绿色 */ /* 实际值 > 目标值绿色样式 */
.percent-exceed { .exceed-target {
color: rgba(54, 181, 138, 1) !important; color: rgba(98, 213, 180, 1) !important;
/* 文字绿色 */
// background: rgba(98, 213, 180, 1) !important;
/* 进度条绿色 */
opacity: 1 !important;
} }
/* 百分比 - 实际值<目标值黄色 */ /* 实际值 < 目标值黄色样式 */
.percent-below { .below-target {
color: rgba(249, 164, 74, 1) !important; color: rgba(249, 164, 74, 1) !important;
/* 文字黄色 */
// background: rgba(249, 164, 74, 1) !important;
/* 进度条黄色 */
opacity: 1 !important;
} }
.yield { .exceed-pro-target {
width: 138px; // color: rgba(98, 213, 180, 1) !important;
margin-top: 3px; /* 文字绿色 */
background: rgba(98, 213, 180, 1) !important;
/* 进度条绿色 */
opacity: 1 !important;
}
/* 实际值 < 目标值:黄色样式 */
.below-pro-target {
// color: rgba(249, 164, 74, 1) !important;
/* 文字黄色 */
background: rgba(249, 164, 74, 1) !important;
/* 进度条黄色 */
opacity: 1 !important;
}
/* 实际值 = 目标值:默认灰色(可自定义) */
.equal-target{
color: rgba(98, 213, 180, 1) !important;
/* 文字绿色 */
// background: rgba(98, 213, 180, 1) !important;
/* 进度条绿色 */
opacity: 1 !important;
}
.equal-pro-target {
// color: rgba(98, 213, 180, 1) !important;
/* 文字绿色 */
background: rgba(98, 213, 180, 1) !important;
/* 进度条绿色 */
opacity: 1 !important;
} }
} }
}
</style> </style>

View File

@@ -1,15 +1,15 @@
<template> <template>
<div class="coreItem"> <div class="coreItem">
<div class="item" :class="`item${index + 1}`" @click="handleItemClick(index)" v-for="(item, index) in itemList" <div class="item" @click="handleItemClick(index)" v-for="(item, index) in itemList"
:key="index"> :key="index">
<div class="unit">{{ item.unit }}</div> <div class="unit">{{ item.unit }}</div>
<div class="item-content"> <div class="item-content">
<div class="content-wrapper"> <div class="content-wrapper">
<div class="left"> <div class="left" v-if="item.unit !== '折旧·万元'">
<div class="number">{{ item.target }}</div> <div class="number">{{ item.target }}</div>
<div class="title">预算值</div> <div class="title">预算值</div>
</div> </div>
<div class="line"></div> <div class="line" v-if="item.unit !== '折旧·万元'"></div>
<div class="right"> <div class="right">
<!-- 实际值颜色动态绑定 --> <!-- 实际值颜色动态绑定 -->
<div class="number" :style="{ color: getColor(index) }"> <div class="number" :style="{ color: getColor(index) }">
@@ -18,7 +18,7 @@
<div class="title">实际值</div> <div class="title">实际值</div>
</div> </div>
</div> </div>
<div class="progress-group"> <div class="progress-group" v-if="item.unit !== '折旧·万元'">
<div class="progress-container"> <div class="progress-container">
<!-- 进度条样式动态绑定 --> <!-- 进度条样式动态绑定 -->
<div class="progress-bar" :style="{ <div class="progress-bar" :style="{
@@ -88,12 +88,17 @@ export default {
{ {
key: 'rawYield', key: 'rawYield',
unit: '原片成品率·%', unit: '原片成品率·%',
route: '/rawSheetYield/rawSheetYield' // 假设这个没有路由 route: '/rawSheetYield/rawSheetYield'
}, },
{ {
key: 'ioYield', key: 'ioYield',
unit: '投入产出率·%', unit: '投入产出率·%',
route: '/inputOutputRatio/inputOutputRatio' // 假设这个没有路由 route: '/inputOutputRatio/inputOutputRatio'
},
{
key: 'depreciation',
unit: '折旧·万元',
route: '/depreciationAnalysis/depreciationAnalysisIndex'
} }
]; ];
@@ -194,7 +199,7 @@ export default {
} }
.item { .item {
width: 252px; width: 166px;
height: 110px; height: 110px;
background: #f9fcff; background: #f9fcff;
padding: 12px; padding: 12px;
@@ -300,10 +305,4 @@ export default {
line-height: 1; line-height: 1;
} }
} }
.item1,
.item2,
.item3 {
width: 166px;
}
</style> </style>

View File

@@ -2,7 +2,7 @@
<div id="dayReport" class="dayReport" :style="styles"> <div id="dayReport" class="dayReport" :style="styles">
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<sidebar v-if="!sidebar.hide" class="sidebar-container" /> <sidebar v-if="!sidebar.hide" class="sidebar-container" />
<ReportHeader :dateData="dateData" top-title="应收账款" :is-full-screen="isFullScreen" <ReportHeader :dateData="dateData" top-title="折旧分析" :is-full-screen="isFullScreen"
@screenfullChange="screenfullChange" @timeRangeChange="handleTimeChange" /> @screenfullChange="screenfullChange" @timeRangeChange="handleTimeChange" />
<div class="main-body" style=" <div class="main-body" style="
flex: 1; flex: 1;
@@ -39,7 +39,7 @@ import { mapState } from "vuex";
import operatingLineChart from "../depreciationAnalysisComponents/operatingLineChart"; import operatingLineChart from "../depreciationAnalysisComponents/operatingLineChart";
import operatingLineChartCumulative from "../depreciationAnalysisComponents/operatingLineChartCumulative.vue"; import operatingLineChartCumulative from "../depreciationAnalysisComponents/operatingLineChartCumulative.vue";
import { getSalesRevenueGroupData } from '@/api/cockpit' import { getDepreciationAnalysisData } from '@/api/cockpit'
export default { export default {
name: "DepreciationAnalysis", name: "DepreciationAnalysis",
components: { components: {
@@ -132,7 +132,7 @@ export default {
// this.getData() // this.getData()
// }, // },
getData() { getData() {
getSalesRevenueGroupData({ getDepreciationAnalysisData({
startTime: this.dateData.startTime, startTime: this.dateData.startTime,
endTime: this.dateData.endTime, endTime: this.dateData.endTime,
sort: this.sort, sort: this.sort,

View File

@@ -16,7 +16,7 @@
gap: 12px; gap: 12px;
grid-template-columns:1624px; grid-template-columns:1624px;
"> ">
<operatingLineChart :dateData="dateData" :monData="monData" /> <operatingLineChart :dateData="dateData" :monthData="monthData" />
</div> </div>
</div> </div>
<div class="top" style="display: flex; gap: 16px;margin-top: 6px;"> <div class="top" style="display: flex; gap: 16px;margin-top: 6px;">
@@ -25,40 +25,27 @@
gap: 12px; gap: 12px;
grid-template-columns: 1624px; grid-template-columns: 1624px;
"> ">
<operatingLineChartCumulative :dateData="dateData" :totalData="totalData" /> <operatingLineChartCumulative :dateData="dateData" :ytdData="ytdData" />
<!-- <keyWork /> -->
</div> </div>
</div> </div>
</div> </div>
<!-- <div class="centerImg" style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1; /* 确保在 backp 之上、内容之下 */
"></div> -->
</div> </div>
</template> </template>
<script> <script>
import ReportHeader from "../components/noRouterHeader.vue"; import ReportHeader from "../components/noRouterHeader.vue";
import { Sidebar } from "../../../layout/components"; import { Sidebar } from "../../../layout/components";
import screenfull from "screenfull"; import screenfull from "screenfull";
// import operatingSalesRevenue from "./operatingComponents/operatingSalesRevenue";
// import premProdStatus from "./components/premProdStatus.vue";
import { mapState } from "vuex"; import { mapState } from "vuex";
import operatingLineChart from "../electricityCostAnalysisComponents/operatingLineChart"; import operatingLineChart from "../accountsReceivableComponents/operatingLineChart";
import operatingLineChartCumulative from "../electricityCostAnalysisComponents/operatingLineChartCumulative.vue"; import operatingLineChartCumulative from "../accountsReceivableComponents/operatingLineChartCumulative.vue";
import { getProfitAnalysisTotalList } from '@/api/cockpit' import { getElectricityCostAnalysisData } from '@/api/cockpit'
import moment from "moment";
export default { export default {
name: "DayReport", name: "AccountsReceivable",
components: { components: {
ReportHeader, ReportHeader,
operatingLineChartCumulative, operatingLineChartCumulative,
operatingLineChart, operatingLineChart,
// premProdStatus,
Sidebar, Sidebar,
}, },
data() { data() {
@@ -68,9 +55,11 @@ export default {
timer: null, timer: null,
beilv: 1, beilv: 1,
value: 100, value: 100,
sort:1,
selectDate:{},
monthData: {},
ytdData:{},
dateData: {}, dateData: {},
monData: [],
totalData: [],
}; };
}, },
@@ -139,20 +128,22 @@ export default {
this.dateData = this.$route.query.dateData ? this.$route.query.dateData : undefined this.dateData = this.$route.query.dateData ? this.$route.query.dateData : undefined
}, },
methods: { methods: {
// sortChange(value) {
// this.sort = value
// this.getData()
// },
getData() { getData() {
getProfitAnalysisTotalList({ getElectricityCostAnalysisData({
startTime: this.dateData.startTime, startTime: this.dateData.startTime,
endTime: this.dateData.endTime, endTime: this.dateData.endTime,
analysisObject: [ sort: this.sort,
"利润总额" index: undefined,
], factory: undefined
levelId: 1,
// timeDim: this.dateData.mode
}).then((res) => { }).then((res) => {
console.log(res); console.log('res==============================',res);
this.monData = res.data.currentMonthData this.monthData= res.data.month
this.totalData = res.data.totalMonthData this.ytdData = res.data.ytd
// this.totalData = res.data.totalData
// this.saleData = res.data.SaleData // this.saleData = res.data.SaleData
// this.premiumProduct = res.data.premiumProduct // this.premiumProduct = res.data.premiumProduct
// this.salesTrendMap = res.data.salesTrendMap // this.salesTrendMap = res.data.salesTrendMap
@@ -161,7 +152,7 @@ export default {
}) })
}, },
handleTimeChange(obj) { handleTimeChange(obj) {
// console.log(obj, 'obj'); console.log(obj, 'obj');
this.dateData= obj this.dateData= obj
this.getData() this.getData()
}, },
@@ -235,14 +226,12 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
@import "~@/assets/styles/mixin.scss"; @import "~@/assets/styles/mixin.scss";
@import "~@/assets/styles/variables.scss"; @import "~@/assets/styles/variables.scss";
.dayReport { .dayReport {
width: 1920px; width: 1920px;
height: 1080px; height: 1080px;
background: url("../../../assets/img/backp.png") no-repeat; background: url("../../../assets/img/backp.png") no-repeat;
background-size: cover; background-size: cover;
} }
.hideSidebar .fixed-header { .hideSidebar .fixed-header {
width: calc(100% - 54px); width: calc(100% - 54px);
} }

View File

@@ -73,7 +73,7 @@ import totalOverview from "../electricityCostAnalysisComponents/totalOverview.vu
import relatedIndicatorsAnalysis from "../electricityCostAnalysisComponents/relatedIndicatorsAnalysis.vue"; import relatedIndicatorsAnalysis from "../electricityCostAnalysisComponents/relatedIndicatorsAnalysis.vue";
import dataTrend from "../electricityCostAnalysisComponents/dataTrend.vue"; import dataTrend from "../electricityCostAnalysisComponents/dataTrend.vue";
import { mapState } from "vuex"; import { mapState } from "vuex";
import { getProfitAnalysisTotalList } from '@/api/cockpit' import { getElectricityCostAnalysisFData } from '@/api/cockpit'
// import PSDO from "./components/PSDO.vue"; // import PSDO from "./components/PSDO.vue";
// import psiLineChart from "./components/psiLineChart.vue"; // import psiLineChart from "./components/psiLineChart.vue";
@@ -108,7 +108,7 @@ export default {
totalData: {}, totalData: {},
trend: [], trend: [],
relatedData: [], relatedData: [],
trendName: '利润总额', trendName: '原片电费',
// cusProData: {}, // cusProData: {},
}; };
}, },
@@ -199,45 +199,26 @@ export default {
const requestParams = { const requestParams = {
startTime: this.dateData.startTime, startTime: this.dateData.startTime,
endTime: this.dateData.endTime, endTime: this.dateData.endTime,
// index: this.index, sort: 1,
// sort: 1, index: this.trendName,
trendName: this.trendName, factory: null
analysisObject: [
"利润总额",
],
// paramList: ['制造成本', '财务费用', '销售费用', '管理费用', '运费'],
levelId: this.factory,
// baseId: Number(this.factory),
}; };
// 调用接口 // 调用接口
getProfitAnalysisTotalList(requestParams).then((res) => { getElectricityCostAnalysisFData(requestParams).then((res) => {
this.monData = res.data.currentMonthData.find(item => { this.monData = res.data.month
return item.name === "利润总额"; this.totalData = res.data.ytd
});
console.log('this.monData', this.monData);
this.totalData = res.data.totalMonthData.find(item => {
return item.name === "利润总额";
});
// this.relatedMon = res.data.relatedMon
this.relatedData = { this.relatedData = {
relatedMon: res.data.currentMonthData.filter(item => { relatedMon: res.data.monthAnalysis,
return item.name !== "利润总额"; relatedTotal: res.data.ytdAnalysis
}), // 兜底月度数据
relatedTotal: res.data.totalMonthData.filter(item => {
return item.name !== "利润总额";
}) // 兜底累计数据
} }
this.trend = res.data.dataTrend this.trend = res.data.dataTrend
}); });
}, },
handleTimeChange(obj) { handleTimeChange(obj) {
this.month = obj.targetMonth this.month = obj.targetMonth
this.dateData = { this.dateData = {
startTime: obj.startTime, startTime: obj.startTime,
endTime: obj.endTime, endTime: obj.endTime,
// mode: obj.mode,
} }
this.getData() this.getData()

View File

@@ -60,16 +60,13 @@ export default {
data() { data() {
return { return {
isDropdownShow: false, isDropdownShow: false,
selectedProfit: '利润总额', // 选中的名称初始为null selectedProfit: '原片电费', // 选中的名称初始为null
profitOptions: [ profitOptions: [
'利润总额', '原片电费',
'销量', '加工电费',
'单价', '外围电费',
'制造成本', '发电量',
'管理费用', '日均发电量'
'销售费用',
'财务费用',
'非经营性利润',
] ]
}; };
}, },

View File

@@ -65,13 +65,13 @@ export default {
*/ */
factoryData() { // 整合原始数据 + 计算flag factoryData() { // 整合原始数据 + 计算flag
return { return {
completeRate: this.monData.proportion ? Number(this.monData.proportion) : 0, completeRate: this.monData.rate ? Number(this.monData.rate) : 0,
diff: this.monData.diffValue, diff: this.monData.diff,
real: this.monData.value, real: this.monData.real,
target: this.monData.targetValue, target: this.monData.target,
thb: this.monData.thb, thb: this.monData.momRate,
// ...rawData, // ...rawData,
flag: this.monData.completed // 新增flag字段 flag: this.monData.rate >= 100 ? 1 : 0,
}; };
} }
}, },

View File

@@ -67,13 +67,11 @@ export default {
computed: { computed: {
indicatorDefs() { indicatorDefs() {
return [ return [
{ key: 'sales', name: '销量', unit: '万', route: '/salesVolumeAnalysis/salesVolumeAnalysisBase'}, { key: 'elecFee', name: '原片电费', unit: '万', route: null},
{ key: 'price', name: '单价', unit: '元/㎡', route: '/unitPriceAnalysis/unitPriceAnalysisBase'}, { key: 'elecCost', name: '加工电费', unit: '元', route: null},
{ key: 'mfgCost', name: '制造成本', unit: '元/㎡', route: '/productionCostAnalysis/productionCostAnalysisBase'}, { key: 'elecCostW', name: '外围电费', unit: '元', route: null},
{ key: 'mgmtFee', name: '管理费用', unit: '万元', route: '/expenseAnalysis/expenseAnalysisBase'}, { key: 'fdl', name: '发电量', unit: '', route: null},
{ key: 'salesFee', name: '销售费用', unit: '万元', route: '/expenseAnalysis/expenseAnalysisBase'}, { key: 'rjfdl', name: '日均发电量', unit: '', route: null},
{ key: 'finFee', name: '财务费用', unit: '万元', route: '/expenseAnalysis/expenseAnalysisBase'},
{ key: 'nonOpProfit', name: '非经营性利润', unit: '万元', route: null}
] ]
}, },
indicators() { indicators() {
@@ -90,7 +88,7 @@ export default {
}) })
}, },
sortedIndicators() { sortedIndicators() {
const unitOrder = ['万㎡', '元/㎡', '万元'] const unitOrder = ['万', '']
const unitRank = (u) => { const unitRank = (u) => {
const idx = unitOrder.indexOf(u) const idx = unitOrder.indexOf(u)
return idx === -1 ? 999 : idx return idx === -1 ? 999 : idx
@@ -173,7 +171,7 @@ export default {
} }
.dashboard { .dashboard {
width: 220px; width: 312px;
height: 205px; height: 205px;
background: #F9FCFF; background: #F9FCFF;
padding: 16px 0 0 10px; padding: 16px 0 0 10px;

View File

@@ -68,13 +68,13 @@ export default {
*/ */
factoryData() { // 整合原始数据 + 计算flag factoryData() { // 整合原始数据 + 计算flag
return { return {
completeRate: this.totalData.proportion ? Number(this.totalData.proportion) : 0, completeRate: this.totalData.rate ? Number(this.totalData.rate) : 0,
diff: this.totalData.diffValue, diff: this.totalData.diff,
real: this.totalData.value, real: this.totalData.real,
target: this.totalData.targetValue, target: this.totalData.target,
thb: this.totalData.thb, thb: this.totalData.yoyRate,
// ...rawData, // ...rawData,
flag: this.totalData.completed// 新增flag字段 flag: this.totalData.rate >= 100 ? 1 : 0,
}; };
} }
}, },

View File

@@ -56,10 +56,11 @@ export default {
value: 100, value: 100,
orderTableData:[], orderTableData:[],
productData: {}, productData: {},
heat:{},
purchase: {}, purchase: {},
dateData:{}, dateData:{},
inventory: {}, inventory: {},
importantWork: {}, importantWork: [],
finance: {}, finance: {},
cost: {}, cost: {},
sale: {}, sale: {},

View File

@@ -39,7 +39,7 @@ import { mapState } from "vuex";
import operatingLineChart from "../inventoryAnalysisComponents/operatingLineChart"; import operatingLineChart from "../inventoryAnalysisComponents/operatingLineChart";
import operatingLineChartCumulative from "../inventoryAnalysisComponents/operatingLineChartCumulative.vue"; import operatingLineChartCumulative from "../inventoryAnalysisComponents/operatingLineChartCumulative.vue";
import { getSalesRevenueGroupData } from '@/api/cockpit' import { getInventoryData } from '@/api/cockpit'
export default { export default {
name: "InventoryAnalysis", name: "InventoryAnalysis",
components: { components: {
@@ -59,6 +59,7 @@ export default {
selectDate:{}, selectDate:{},
monthData: {}, monthData: {},
ytdData:{}, ytdData:{},
dateData:{}
}; };
}, },
@@ -132,7 +133,7 @@ export default {
// this.getData() // this.getData()
// }, // },
getData() { getData() {
getSalesRevenueGroupData({ getInventoryData({
startTime: this.dateData.startTime, startTime: this.dateData.startTime,
endTime: this.dateData.endTime, endTime: this.dateData.endTime,
sort: this.sort, sort: this.sort,

View File

@@ -147,7 +147,6 @@ export default {
"经营性利润" "经营性利润"
], ],
levelId:1, levelId:1,
// timeDim: this.dateData.mode
}).then((res) => { }).then((res) => {
console.log(res); console.log(res);
this.monData = res.data.currentMonthData this.monData = res.data.currentMonthData

View File

@@ -143,7 +143,7 @@ export default {
{ offset: 1, color: 'rgba(40, 138, 255, 0)' } { offset: 1, color: 'rgba(40, 138, 255, 0)' }
]) ])
}, },
data: data.rate || [], data: data.rates || [],
symbol: 'circle', symbol: 'circle',
symbolSize: 6 symbolSize: 6
}, },

View File

@@ -72,6 +72,7 @@ export default {
selectDate:{}, selectDate:{},
monthData: {}, monthData: {},
ytdData:{}, ytdData:{},
dateData: {},
}; };
}, },

View File

@@ -189,23 +189,23 @@ export default {
startTime: this.dateData.startTime, startTime: this.dateData.startTime,
endTime: this.dateData.endTime, endTime: this.dateData.endTime,
trendName: '原料' + this.meterialName + this.trendName, trendName: '原料' + this.meterialName + this.trendName,
analysisObject: ['原料' + this.meterialName], analysisObject: [this.meterialName],
levelId: this.factory, levelId: this.factory,
}; };
// 调用接口 // 调用接口
getSingleMaterialAnalysis(requestParams).then((res) => { getSingleMaterialAnalysis(requestParams).then((res) => {
this.monData = res.data.currentMonthData.find(item => { this.monData = res.data.currentMonthData.find(item => {
return item.name === '原料' + this.meterialName; return item.name === this.meterialName + '成本';
}); });
this.totalData = res.data.totalMonthData.find(item => { this.totalData = res.data.totalMonthData.find(item => {
return item.name === '原料' + this.meterialName; return item.name === this.meterialName + '成本';
}); });
this.relatedData = { this.relatedData = {
relatedMon: res.data.currentMonthData.filter(item => { relatedMon: res.data.currentMonthData.filter(item => {
return item.name !== '原料' + this.meterialName; return item.name !== this.meterialName + '成本';
}), // 兜底月度数据 }), // 兜底月度数据
relatedTotal: res.data.totalMonthData.filter(item => { relatedTotal: res.data.totalMonthData.filter(item => {
return item.name !== '原料' + this.meterialName; return item.name !== this.meterialName + '成本';
}) // 兜底累计数据 }) // 兜底累计数据
} }
this.trend = res.data.dataTrend this.trend = res.data.dataTrend

View File

@@ -108,9 +108,7 @@ export default {
totalData: {}, totalData: {},
trend: [], trend: [],
relatedData: {}, relatedData: {},
trendName: '原片原料成本', trendName: '原片原料',
// monthRelatedData: [],
// totalRelatedData: [],
}; };
}, },

View File

@@ -84,7 +84,7 @@ export default {
overheadName:'', overheadName:'',
overheadOptions:[ overheadOptions:[
{value:'包材',label:'包材'}, {value:'包材',label:'包材'},
{value:'备品丶机物料',label:'备品丶机物料'}, {value:'备件、机物料',label:'备件、机物料'},
{value:'折旧',label:'折旧'}, {value:'折旧',label:'折旧'},
{value:'其他',label:'其他'} {value:'其他',label:'其他'}
] ]

View File

@@ -39,7 +39,7 @@
grid-template-columns: 1624px; grid-template-columns: 1624px;
"> ">
<!-- <monthlyRelatedMetrics :itemData="renderList" :title="'月度·相关指标分析'" /> --> <!-- <monthlyRelatedMetrics :itemData="renderList" :title="'月度·相关指标分析'" /> -->
<relateSingleFuelCostAnalysis :relatedData="relatedData" :title="'相关指标分析'" /> <relateSingleFuelCostAnalysis :fuelName='fuelName' :relatedData="relatedData" :title="'相关指标分析'" />
</div> </div>
</div> </div>
@@ -213,7 +213,7 @@ export default {
// index: this.index, // index: this.index,
// sort: 1, // sort: 1,
trendName: this.trendName, trendName: this.trendName,
analysisObject: [this.fuelName + '成本'], analysisObject: [this.fuelName],
// paramList: ['制造成本', '财务费用', '销售费用', '管理费用', '运费'], // paramList: ['制造成本', '财务费用', '销售费用', '管理费用', '运费'],
levelId: this.factory, levelId: this.factory,
// baseId: Number(this.factory), // baseId: Number(this.factory),

View File

@@ -211,7 +211,7 @@ export default {
// index: this.index, // index: this.index,
// sort: 1, // sort: 1,
trendName: this.trendName, trendName: this.trendName,
analysisObject: [this.fuelName + '成本'], analysisObject: [this.fuelName],
// paramList: ['制造成本', '财务费用', '销售费用', '管理费用', '运费'], // paramList: ['制造成本', '财务费用', '销售费用', '管理费用', '运费'],
levelId: this.factory, levelId: this.factory,
// baseId: Number(this.factory), // baseId: Number(this.factory),

View File

@@ -64,7 +64,7 @@ export default {
profitOptions: [ profitOptions: [
'原片制造费用成本', '原片制造费用成本',
'包材', '包材',
'备品丶机物料', '备件、机物料',
'折旧', '折旧',
'其他', '其他',
] ]

View File

@@ -60,9 +60,9 @@ export default {
data() { data() {
return { return {
isDropdownShow: false, isDropdownShow: false,
selectedProfit: '原片原料成本', // 选中的名称初始为null selectedProfit: '原片原料', // 选中的名称初始为null
profitOptions: [ profitOptions: [
'原片原料成本', '原片原料',
'硅砂', '硅砂',
'纯碱', '纯碱',
'白云石', '白云石',

View File

@@ -63,7 +63,7 @@ export default {
selectedProfit: '制造费用', // 选中的名称初始为null selectedProfit: '制造费用', // 选中的名称初始为null
profitOptions: [ profitOptions: [
'制造费用', '制造费用',
'备品丶机物料', '备件、机物料',
'折旧', '折旧',
'其他', '其他',
] ]

View File

@@ -135,9 +135,9 @@ export default {
mounted() { mounted() {
let timeArr = [] let timeArr = []
if (this.$route.query.startTime && this.$route.query.endTime) { if (this.$route.query.startTime && this.$route.query.endTime) {
timeArr = [moment(Number(this.$route.query.startTime)).format('YYYY-MM'), moment(Number(this.$route.query.endTime)).format('YYYY-MM')] timeArr = [moment(Number(this.$route.query.startTime)).format('YYYY-MM-DD'), moment(Number(this.$route.query.endTime)).format('YYYY-MM-DD')]
}else{ }else{
timeArr = [moment().startOf('month').format('YYYY-MM'), moment().endOf('month').format('YYYY-MM')] timeArr = [moment().startOf('month').format('YYYY-MM-DD'), moment().endOf('month').format('YYYY-MM-DD')]
}; };
this.$refs.searchBarForm.formInline.timeValMonth = timeArr this.$refs.searchBarForm.formInline.timeValMonth = timeArr
this.listQuery.startTime = moment(timeArr[0]).startOf('day').valueOf(); this.listQuery.startTime = moment(timeArr[0]).startOf('day').valueOf();
@@ -195,8 +195,8 @@ export default {
this.listQuery.pageNo = 1; this.listQuery.pageNo = 1;
this.listQuery.pageSize = 20; this.listQuery.pageSize = 20;
this.listQuery.status = val.status ? val.status : undefined; this.listQuery.status = val.status ? val.status : undefined;
this.listQuery.startTime = moment(val.timeValMonth[0]).startOf('day').valueOf(); this.listQuery.startTime = moment(moment(val.timeValMonth[0]).startOf('month').format('YYYY-MM-DD')).startOf('day').valueOf();
this.listQuery.endTime = moment(val.timeValMonth[1]).endOf('day').valueOf(); this.listQuery.endTime = moment(moment(val.timeValMonth[1]).endOf('month').format('YYYY-MM-DD')).endOf('day').valueOf();
switch (val.btnName) { switch (val.btnName) {
case 'search': case 'search':
this.getDataList(); this.getDataList();