Compare commits

...

3 Commits

Author SHA1 Message Date
21aad8176f 报表时间&经营性利润排序等bug 2026-03-30 14:13:51 +08:00
f208c3c744 路由跳转逻辑bug修复 2026-03-30 09:27:47 +08:00
b05d42cfc8 3.27修改入参及数据获取字段变更 2026-03-30 08:49:16 +08:00
26 changed files with 126 additions and 75 deletions

View File

@@ -8,11 +8,8 @@ import { isRelogin } from '@/utils/request'
NProgress.configure({ showSpinner: false })
/**
* 从菜单树中查找 jumpFlag===1 的默认跳转路径
* 若打标在父节点则取其下第一个可见叶子路径;若在叶子则直接返回该路径
*/
function findDefaultPathFromMenus(menus) {
// 从菜单树中查找第一个可见叶子菜单路径(按接口返回顺序)
function findFirstLeafPathFromMenus(menus) {
if (!Array.isArray(menus) || menus.length === 0) return null
function dfs(list, parentPath = '') {
@@ -22,23 +19,34 @@ function findDefaultPathFromMenus(menus) {
const currentPath = rawPath.startsWith('/')
? rawPath
: `${parentPath}/${rawPath}`.replace(/\/+/g, '/')
if (item.jumpFlag === 1) {
if (item.children && item.children.length > 0) {
const childPath = dfs(item.children, currentPath)
return childPath != null ? childPath : currentPath
}
return currentPath
}
if (item.children && item.children.length > 0) {
const found = dfs(item.children, currentPath)
if (found != null) return found
} else {
return currentPath
}
}
return null
}
return dfs(menus)
}
function findFirstLeafPathFromRoutes(routes) {
if (!Array.isArray(routes) || routes.length === 0) return null
const stack = [...routes]
while (stack.length) {
const route = stack.shift()
if (!route || route.hidden === true) continue
if (Array.isArray(route.children) && route.children.length > 0) {
stack.unshift(...route.children)
continue
}
const p = route.path || ''
if (typeof p === 'string' && p.startsWith('/') && p !== '/404') {
return p
}
}
return null
}
// 增加三方登陆 update by 芋艿
const whiteList = ['/login', '/social-login', '/auth-redirect', '/bind', '/register', '/oauthLogin/gitee']
@@ -65,11 +73,16 @@ router.beforeEach((to, from, next) => {
store.dispatch('GenerateRoutes', userInfo.menus).then(accessRoutes => {
// 根据 roles 权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
const defaultPath = findDefaultPathFromMenus(userInfo.menus) || '/'
const menuDefaultPath = findFirstLeafPathFromMenus(userInfo.menus)
const routeFallbackPath = findFirstLeafPathFromRoutes(accessRoutes)
const defaultPath = menuDefaultPath || routeFallbackPath || '/'
store.dispatch('SetDefaultPath', defaultPath)
// 仅当目标为根路径 '/' 时跳默认页;否则保持当前路径(含刷新场景),避免刷新被误判为“未匹配”而跳到默认页
if (to.path === '/') {
next({ path: defaultPath, replace: true })
const matched = router.match(defaultPath)
const hasMatch = matched && Array.isArray(matched.matched) && matched.matched.length > 0
const safePath = hasMatch ? defaultPath : (routeFallbackPath || '/')
next({ path: safePath, replace: true })
} else {
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成当前页刷新时保留 to 的路径
}

View File

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

View File

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

View File

@@ -65,7 +65,7 @@
'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;">
<div class="yield" style="font-size: 18px;margin-bottom: 4px;">
{{ item.progress }}
</div>
<div class="unit">%</div>
@@ -359,12 +359,11 @@ export default {
text-align: center;
.title {
margin-top: 10px;
margin-top:4px;
height: 12px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
margin-right: 8px;
color: #000000;
line-height: 12px;
text-align: left;
@@ -372,7 +371,7 @@ export default {
}
.unit {
margin-top: 10px;
margin-top: 4px;
margin-right: 14px;
height: 12px;
font-family: PingFangSC, PingFang SC;

View File

@@ -149,7 +149,6 @@ export default {
levelId:1,
// timeDim: this.dateData.mode
}).then((res) => {
console.log(res);
this.monData = res.data.currentMonthData
this.totalData = res.data.totalMonthData
// this.totalData = res.data.totalData

View File

@@ -121,6 +121,7 @@ export default {
// 最终传递给图表的排序后数据
chartD() {
const data = this.currentDataSource;
console.log('charData+++++++++++++++++++++++++++++',data)
const salesData = {
allPlaceNames: this.locations,
series: [
@@ -143,7 +144,7 @@ export default {
{ offset: 1, color: 'rgba(40, 138, 255, 0)' }
])
},
data: data.rate || [],
data: data.rates || [],
symbol: 'circle',
symbolSize: 6
},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -90,6 +90,7 @@ export default {
const salesData = {
allPlaceNames: this.locations,
unit:'元/㎡',
series: [
// 1. 完成率(折线图)
{

View File

@@ -35,7 +35,7 @@
<div class="dropdown-options" v-if="isDropdownShow">
<div class="dropdown-option" v-for="(item, index) in profitOptions" :key="index"
@click.stop="selectProfit(item)">
{{ item }}
{{ item.name }}
</div>
</div>
</div>
@@ -61,12 +61,22 @@ export default {
return {
isDropdownShow: false,
selectedProfit: '天然气', // 选中的名称初始为null
profitOptions: [
'天然气',
'LNG液化天然气',
'重油',
'水',
]
profitOptions: [{
name: '天然气',
unit:'元/㎡',
},
{
name: 'LNG液化天然气',
unit:'元/㎡',
},
{
name: '重油',
unit:'元/㎡',
},
{
name: '水',
unit:'元/㎡',
}],
};
},
computed: {
@@ -88,6 +98,7 @@ export default {
const salesData = {
allPlaceNames: this.locations,
unit:'元/㎡',
series: [
// 1. 完成率(折线图)
{
@@ -246,9 +257,10 @@ export default {
},
methods: {
selectProfit(item) {
this.selectedProfit = item;
this.selectedProfit = item.name;
this.unit = item.unit;
this.isDropdownShow = false;
this.$emit('handleGetItemData', item)
this.$emit('handleGetItemData', item.name)
}
},
};

View File

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

View File

@@ -60,9 +60,9 @@ export default {
data() {
return {
isDropdownShow: false,
selectedProfit: '原片原料成本', // 选中的名称初始为null
selectedProfit: '原片原料', // 选中的名称初始为null
profitOptions: [
'原片原料成本',
'原片原料',
'硅砂',
'海砂',
'纯碱',
@@ -90,6 +90,7 @@ export default {
const salesData = {
allPlaceNames: this.locations,
unit:'元/㎡',
series: [
// 1. 完成率(折线图)
{

View File

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

View File

@@ -87,6 +87,7 @@ export default {
const salesData = {
allPlaceNames: this.locations,
unit:'元/㎡',
series: [
// 1. 完成率(折线图)
{

View File

@@ -35,7 +35,7 @@
<div class="dropdown-options" v-if="isDropdownShow">
<div class="dropdown-option" v-for="(item, index) in profitOptions" :key="index"
@click.stop="selectProfit(item)">
{{ item }}
{{ item.name }}
</div>
</div>
</div>
@@ -61,12 +61,23 @@ export default {
return {
isDropdownShow: false,
selectedProfit: '采购单价', // 选中的名称初始为null
profitOptions: [
'采购单价',
'产量',
'单耗',
'消耗量',
]
profitOptions: [{
name: '采购单价',
unit: '元/吨'
},
{
name: '产量',
unit: '吨'
},
{
name: '单耗',
unit: 'kg/㎡'
},
{
name: '消耗量',
unit: '吨'
}],
unit:'元/吨',
};
},
computed: {
@@ -88,6 +99,7 @@ export default {
const salesData = {
allPlaceNames: this.locations,
unit:this.unit,
series: [
// 1. 完成率(折线图)
{
@@ -247,9 +259,10 @@ export default {
methods: {
selectProfit(item) {
console.log('aaaaaa',item)
this.selectedProfit = item;
this.selectedProfit = item.name;
this.isDropdownShow = false;
this.$emit('handleGetItemData', item)
this.$emit('handleGetItemData', item.name)
this.unit = item.unit;
}
},
};

View File

@@ -5,7 +5,7 @@
<div class="kpi-content" style="padding: 14px 16px; display: flex; width: 100%;">
<!-- 新增topItem 专属包裹容器统一控制样式和布局原有行内样式不变 -->
<div class="topItem-container" style="display: flex; gap: 8px;">
<div class="dashboard left" @click="handleDashboardClick('备品丶机物料')">
<div class="dashboard left" @click="handleDashboardClick('备件、机物料')">
<div class="title">
备件机物料·/
</div>
@@ -76,7 +76,7 @@ export default {
computed: {
// 1. 备件丶机物料数据:精准筛选对应名称数据,兜底值统一
sparePartsData() {
return this.relatedData.find(item => (item.name || '').includes('备品丶机物料')) || {
return this.relatedData.find(item => (item.name || '').includes('备件、机物料')) || {
targetValue: 0,
value: 0,
completed: 0,

View File

@@ -7,28 +7,28 @@
<div class="topItem-container" style="display: flex; gap: 8px;">
<!-- 天然气组件绑定对应筛选数据点击传递物料名和路由 -->
<div class="dashboard left" @click="handleDashboardClick('天然气', 'singleCombustible')">
<div class="title">天然气·/</div>
<div class="title">天然气·/</div>
<div class="line">
<operatingSingleBar :detailData="naturalGasData"></operatingSingleBar>
</div>
</div>
<!-- LNG液化天然气组件绑定对应筛选数据 -->
<div class="dashboard right" @click="handleDashboardClick('LNG液化天然气', 'singleCombustible')">
<div class="title">LNG液化天然气·/</div>
<div class="title">LNG液化天然气·/</div>
<div class="line">
<operatingSingleBar :detailData="lngData"></operatingSingleBar>
</div>
</div>
<!-- 重油组件绑定对应筛选数据 -->
<div class="dashboard right" @click="handleDashboardClick('重油', 'singleCombustible')">
<div class="title">重油·/</div>
<div class="title">重油·/</div>
<div class="line">
<operatingSingleBar :detailData="heavyOilData"></operatingSingleBar>
</div>
</div>
<!-- 水组件绑定对应筛选数据 -->
<div class="dashboard right" @click="handleDashboardClick('水', 'singleCombustible')">
<div class="title">·/</div>
<div class="title">·/</div>
<div class="line">
<operatingSingleBar :detailData="waterData"></operatingSingleBar>
</div>

View File

@@ -15,7 +15,7 @@
<operatingSingleBar :detailData="packagingData"></operatingSingleBar>
</div>
</div>
<div class="dashboard right" @click="handleDashboardClick('备品丶机物料')">
<div class="dashboard right" @click="handleDashboardClick('备件、机物料')">
<div class="title">
备件机物料·/
</div>
@@ -110,7 +110,7 @@ export default {
},
// 2. 备件丶机物料数据:精准筛选
sparePartsData() {
return this.activeData.find(item => (item.name || '').includes('备品丶机物料')) || {
return this.activeData.find(item => (item.name || '').includes('备件、机物料')) || {
targetValue: 0,
value: 0,
completed: 0,

View File

@@ -13,12 +13,12 @@
</div>
</div>
<!-- 2. 海砂组件传递对应筛选数据 -->
<div class="dashboard right" @click="handleDashboardClick('海砂', 'SIMFRMCostAnalysis')">
<!-- <div class="dashboard right" @click="handleDashboardClick('海砂', 'SIMFRMCostAnalysis')">
<div class="title">海砂·/</div>
<div class="line">
<operatingSingleBar :detailData="seaSandData"></operatingSingleBar>
</div>
</div>
</div> -->
<!-- 3. 纯碱组件传递对应筛选数据 -->
<div class="dashboard right" @click="handleDashboardClick('纯碱', 'SIMFRMCostAnalysis')">
<div class="title">纯碱·/</div>
@@ -203,7 +203,7 @@ export default {
}
.dashboard {
width: 310px;
width: 390px;
height: 205px;
background: #F9FCFF;
padding: 16px 0 0 10px;

View File

@@ -8,7 +8,7 @@
<div class="topItem-container" style="display: flex; gap: 8px;">
<div class="dashboard left">
<div class="title">
采购单价·/
采购单价·{{fuelName=='天然气'||fuelName=='LNG液化天然气'||fuelName=='水'?'元/m³':'万元'}}
</div>
<div class="line">
<!-- 绑定对应数据新增数据绑定样式不变 -->
@@ -83,6 +83,10 @@ export default {
type: String,
default: '' // 默认空字符串,保持原有配置
},
fuelName:{
type: String,
default: ''
}
},
data() {
return {

View File

@@ -24,7 +24,7 @@
</div>
<div class="dashboard right">
<div class="title">
单耗·
单耗·kg/
</div>
<div class="line">
<operatingSingleBar :detailData="unitHaoData"></operatingSingleBar>

View File

@@ -5,7 +5,7 @@
<div class="kpi-content" style="padding: 14px 16px; display: flex; width: 100%;">
<!-- 新增topItem 专属包裹容器统一控制样式和布局原有行内样式不变 -->
<div class="topItem-container" style="display: flex; gap: 8px;">
<div class="dashboard left" @click="handleDashboardClick('备品丶机物料')">
<div class="dashboard left" @click="handleDashboardClick('备件、机物料')">
<div class="title">
备件机物料·/
</div>
@@ -76,7 +76,7 @@ export default {
computed: {
// 1. 备件丶机物料数据:精准筛选对应名称数据,兜底值统一
sparePartsData() {
return this.relatedData.find(item => (item.name || '').includes('备品丶机物料')) || {
return this.relatedData.find(item => (item.name || '').includes('备件、机物料')) || {
targetValue: 0,
value: 0,
completed: 0,

View File

@@ -135,9 +135,9 @@ export default {
mounted() {
let timeArr = []
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{
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.listQuery.startTime = moment(timeArr[0]).startOf('day').valueOf();
@@ -195,8 +195,8 @@ export default {
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 20;
this.listQuery.status = val.status ? val.status : undefined;
this.listQuery.startTime = moment(val.timeValMonth[0]).startOf('day').valueOf();
this.listQuery.endTime = moment(val.timeValMonth[1]).endOf('day').valueOf();
this.listQuery.startTime = moment(moment(val.timeValMonth[0]).startOf('month').format('YYYY-MM-DD')).startOf('day').valueOf();
this.listQuery.endTime = moment(moment(val.timeValMonth[1]).endOf('month').format('YYYY-MM-DD')).endOf('day').valueOf();
switch (val.btnName) {
case 'search':
this.getDataList();