驾驶舱报表&指标填报&接口添加loading

This commit is contained in:
2026-03-11 09:54:39 +08:00
parent 1d5af53e1a
commit 4d3b2b13b8
12 changed files with 629 additions and 294 deletions

View File

@@ -143,7 +143,7 @@ h6 {
.pagination-container .el-pagination {
right: 0;
position: absolute;
position: absolute !important;
}
@media (max-width: 768px) {

View File

@@ -1,5 +1,5 @@
import axios from 'axios'
import {Message, MessageBox, Notification} from 'element-ui'
import {Message, MessageBox, Notification, Loading} from 'element-ui'
import store from '@/store'
import {getAccessToken, getRefreshToken, getTenantId, setToken, getVisitTenantId} from '@/utils/auth'
import errorCode from '@/utils/errorCode'
@@ -31,8 +31,36 @@ const service = axios.create({
// 禁用 Cookie 等信息
withCredentials: false,
})
let loadingInstance = null
function startLoading() {
loadingInstance = Loading.service({
fullscreen: false,
text: '拼命加载中...',
background: 'rgba(0, 0, 0, 0.1)'
})
}
function endLoading() {
loadingInstance.close()
}
let needLoadingRequestCount = 0
function showFullScreenLoading() {
if (needLoadingRequestCount === 0) {
startLoading()
}
needLoadingRequestCount++
}
function tryHideFullScreenLoading() {
if (needLoadingRequestCount <= 0) return
needLoadingRequestCount--
if (needLoadingRequestCount === 0) {
endLoading()
}
}
// request拦截器
service.interceptors.request.use(config => {
showFullScreenLoading()
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
if (getAccessToken() && !isToken) {
@@ -88,12 +116,14 @@ service.interceptors.request.use(config => {
}
return config
}, error => {
tryHideFullScreenLoading()
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(async res => {
tryHideFullScreenLoading()
let { data } = res
// 未设置状态码则默认成功状态
// 二进制数据则直接返回,例如说 Excel 导出
@@ -202,6 +232,7 @@ service.interceptors.response.use(async res => {
}
}, error => {
console.log('err' + error)
tryHideFullScreenLoading()
let {message} = error;
if (message === "Network Error") {
message = "后端接口连接异常";

View File

@@ -8,7 +8,7 @@
<div style="width: 4px;height: 16px;background: #0B58FF;border-radius: 1px;margin-top: 10px;"></div>
<el-form :inline="true" :model="form" class="demo-form-inline">
<el-form-item label="所属层级">
<el-select v-model="form.levelId" placeholder="请选择">
<el-select v-model="form.levelId" placeholder="请选择" @change='handleLevelChange'>
<el-option v-for="item in levelLList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
@@ -358,6 +358,9 @@ export default {
this.tableData = [];
});
},
handleLevelChange(id) {
this.$emit('updateLevel', id)
},
// 表格单元格数据变更回调
inputChange(val) {
// 安全修改:判断索引是否存在,避免数组越界
@@ -377,7 +380,7 @@ export default {
// 清空并重新请求数据,恢复原始状态
this.$nextTick(() => {
this.tableData = [];
this.getData();
this.getDataPage();
});
},
// 初始化表格列配置核心精准控制inputArea挂载
@@ -498,7 +501,8 @@ export default {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles();
this.getData()
this.getDataPage();
this.$emit('updateLeft')
} else {
this.$message.error(`上传失败:${response.data.msg || '未知错误'}`)
}

View File

@@ -8,7 +8,7 @@
<div style="width: 4px;height: 16px;background: #0B58FF;border-radius: 1px;margin-top: 10px;"></div>
<el-form :inline="true" :model="form" class="demo-form-inline">
<el-form-item label="所属层级">
<el-select v-model="form.levelId" placeholder="请选择">
<el-select v-model="form.levelId" placeholder="请选择" @change='handleLevelChange'>
<el-option v-for="item in levelLList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
@@ -214,9 +214,10 @@ export default {
// 清空并重新请求数据,恢复原始状态
this.$nextTick(() => {
this.tableData = [];
this.getData();
this.getDataPage();
});
this.$modal.msgSuccess("保存成功");
this.$emit('updateLeft')
}).catch(() => { });
},
// 取消编辑,恢复只读模式
@@ -227,7 +228,7 @@ export default {
// 清空并重新请求数据,恢复原始状态
this.$nextTick(() => {
this.tableData = [];
this.getData();
this.getDataPage();
});
console.log('已取消编辑,恢复原始数据');
},
@@ -238,7 +239,7 @@ export default {
// 清空并重新请求数据,恢复原始状态
this.$nextTick(() => {
this.tableData = [];
this.getData();
this.getDataPage();
});
},
@@ -290,6 +291,7 @@ export default {
getLevelStruc().then((res) => {
this.levelLList = res.data || [];
this.form.levelId = this.levelLList[0].id;
this.$emit('updateLevel', this.levelLList[0].id)
this.getDataPage()
}).catch(err => {
console.error('获取所属层级失败:', err);
@@ -320,6 +322,9 @@ export default {
});
},
handleLevelChange(id) {
this.$emit('updateLevel', id)
},
// 查询按钮点击事件(可根据需求扩展逻辑)
onSubmit() {
@@ -372,7 +377,8 @@ export default {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles();
this.getData()
this.getDataPage();
this.$emit('updateLeft')
} else {
this.$message.error(`上传失败:${response.data.msg || '未知错误'}`)
}

View File

@@ -27,7 +27,7 @@ export default {
chart: null,
// 固定3条默认数据作为展示模板
parentItemList: [
{ name: "制造成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
{ name: "制造成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
{ name: "原片成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
{ name: "加工成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
]

View File

@@ -17,7 +17,7 @@
grid-template-columns:416px 1192px;
">
<indicatorCalendar :calendarList="calendarList" />
<indicatorDetails @updateLeft='getData'/>
<indicatorDetails @updateLeft='getData' @updateLevel='getLevel'/>
</div>
</div>
<!-- <div class="top" style="margin-top: -20px; display: flex; gap: 16px">
@@ -78,6 +78,7 @@ export default {
monthData: {},
ytdData: {},
calendarList:{},
levelId:null
};
},
@@ -143,20 +144,21 @@ export default {
this.beilv = _this.clientWidth / 1920;
})();
};
this.getData()
},
methods: {
// 层级变动
getLevel(id) {
this.levelId = id
this.getData()
},
getData() {
getRealMonthCalendar().then((res) => {
getRealMonthCalendar({
levelId: this.levelId
}).then((res) => {
console.log(res, 'res');
this.calendarList = res.data
})
},
handleTimeChange(obj) {
console.log(obj, 'obj');
this.dateData= obj
this.getData()
},
handleClickOutside() {
this.$store.dispatch("app/closeSideBar", { withoutAnimation: false });
},

View File

@@ -207,7 +207,7 @@ export default {
// sort: 1,
trendName: this.trendName,
analysisObject: [
"制造成本",
"制造成本",
],
// paramList: ['制造成本', '财务费用', '销售费用', '管理费用', '运费'],
levelId: this.factory,

View File

@@ -94,7 +94,7 @@ export default {
totalData: {},
trend: [],
relatedData: {},
trendName: '备丶机物料',
trendName: '备丶机物料成本',
};
},

View File

@@ -60,9 +60,9 @@ export default {
data() {
return {
isDropdownShow: false,
selectedProfit: '制造成本', // 选中的名称初始为null
selectedProfit: '制造成本', // 选中的名称初始为null
profitOptions: [
'制造成本',
'制造成本',
'原片成本',
'加工成本',
]

View File

@@ -2,25 +2,27 @@
<div class="app-container">
<!-- 新增工具栏包含左侧按钮保存/取消和右侧返回按钮 -->
<div class="table-toolbar">
<!-- 左侧修改场景显示保存和取消按钮 -->
<div class="left-btns" v-if="isEditMode">
<!-- 左侧固定显示返回按钮 -->
<div>
<el-button @click="goback" icon="el-icon-back">返回</el-button>
</div>
<!-- 右侧修改场景显示保存和取消按钮 -->
<div class="right-btns" v-if="isEditMode">
<el-button type="primary" @click="dataFormSubmit">保存</el-button>
<el-button @click="cancelEdit" :loading="dataListLoading">取消</el-button>
</div>
<!-- 右侧固定显示返回按钮 -->
<div class="right-btns">
<el-button @click="goback" icon="el-icon-back">返回</el-button>
</div>
</div>
<base-table @emitFun="inputChange" class="right-aside" :table-props="tableProps" :page="listQuery.pageNo"
:limit="listQuery.pageSize" :table-data="tableData" v-loading="dataListLoading" ref="baseTable"></base-table>
<pagination :limit.sync="listQuery.pageSize" :page.sync="listQuery.pageNo" :total="total" @pagination="getData" :background="true" />
</div>
</template>
<script>
import inputArea from './inputArea.vue'
import { getDataBackUpDetail, updateDataBackUpDetail } from '@/api/cockpit';
import { publicFormatter } from '@/utils/dict';
export default {
components: { inputArea },
@@ -34,9 +36,10 @@ export default {
listQuery: {
time: undefined,
timeDim: 10,
pageNo: 1, // 补充分页默认值避免undefined
pageSize: 10 // 补充分页默认值
pageNo: 1,
pageSize: 10
},
total:0,
isEditMode: false,
dataListLoading: false // 新增:加载状态
};
@@ -52,28 +55,23 @@ export default {
methods: {
inputChange(val) {
console.log('修改的数据:', val);
// 安全修改:判断索引是否存在,避免越界
if (this.tableData[val._pageIndex - 1]) {
this.tableData[val._pageIndex - 1][val.prop] = val[val.prop];
// 同步更新状态为“已修改”status=1
this.tableData[val._pageIndex - 1].status = 1;
}
let no = val._pageIndex - 1 - (this.listQuery.pageNo - 1) * this.listQuery.pageSize
this.tableData[no][val.prop] = val[val.prop];
},
// 重构:获取数据并缓存原始数据
getData() {
this.dataListLoading = true; // 开启加载
getDataBackUpDetail({
timeDim: this.listQuery.timeDim,
time: this.listQuery.time,
})
getDataBackUpDetail({...this.listQuery})
.then(res => {
console.log('接口返回数据:', res);
this.tableData = res.data || [];
this.tableData = res.data.list || [];
this.total = res.data.total || 0;
})
.catch(err => {
console.error('获取数据失败:', err);
this.tableData = [];
this.originTableData = [];
this.total = 0;
})
.finally(() => {
this.dataListLoading = false; // 关闭加载
@@ -96,8 +94,9 @@ export default {
label: '所属层级'
},
{
prop: 'unitName',
label: '单位'
prop: 'unit',
label: '单位',
filter: publicFormatter('lb_dw')
},
{
prop: 'value',
@@ -112,10 +111,20 @@ export default {
if (isEdit) {
// 编辑模式:添加输入组件
this.tableProps = baseTableProps.map(item => ({
...item,
subcomponent: inputArea
}));
// this.tableProps = baseTableProps.map(item => ({
// ...item,
// subcomponent: inputArea
// }));
this.tableProps = baseTableProps.map(item=>{
if (item.prop === 'value') {
return {
...item,
subcomponent: inputArea
};
} else {
return item;
}
})
} else {
// 只读模式:使用基础配置
this.tableProps = baseTableProps;
@@ -134,7 +143,7 @@ export default {
updateDataBackUpDetail(this.tableData)
.then((res) => {
this.$modal.msgSuccess('修改成功');
this.goback();
this.getData();
})
.catch(err => {
console.error('修改失败:', err);
@@ -146,7 +155,14 @@ export default {
},
// 返回上一页
goback() {
this.$router.go(-1);
// this.$router.go(-1);
this.$router.push({
path: 'cockpitReport',
query: {
startTime:this.$route.query.startTime,
endTime:this.$route.query.endTime
}
})
},
},
};
@@ -163,7 +179,7 @@ export default {
}
/* 按钮间距 */
.left-btns>el-button {
.right-btns>el-button {
margin-right: 8px;
}

View File

@@ -0,0 +1,469 @@
<template>
<div class="app-container">
<!-- :isFold="true" 控制展开 -->
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick"
@select-changed="selectType" />
<base-table v-if="tableData.length" class="right-aside" v-loading="dataListLoading" :table-props="tableProps"
:page="listQuery.pageNo" :limit="listQuery.pageSize" :table-data="tableData">
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="200" label="操作" :method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<!-- <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList" /> -->
</div>
</template>
<script>
// import { parseTime } from '../../mixins/code-filter';
import { getDataBackUp, exportDataBackUp, recoverDataBackUp } from '@/api/cockpit';
// import { exportCostOriginRadioHisData } from '../../../../api/core/monitoring';
import { parseTime } from "@/utils/ruoyi";
import moment from 'moment';
const tableProps = [
{
prop: 'reportType',
label: '报表类型'
},
{
prop: 'time',
label: '日期',
width: 160,
filter: parseTime,
// fatter
},
{
prop: 'status',
label: '状态',
filter: (v => v === 0 ? '正常' : '已修改' ),
},
];
export default {
components: {
},
data() {
return {
urlOptions: {
// getDataListURL:
},
tableData: [
// {
// reportType: 'reportType',
// status: 'reportType',
// time: '报表类型'
// },
],
listQuery: {
pageSize: 10,
pageNo: 1,
timeDim: undefined,
startTime: undefined,
endTime: undefined
},
pdLineList: [],
exportLoading: false,
dataListLoading: false,
selectedList: [],
dialogVisible: false,
addOrEditTitle: '',
addOrUpdateVisible: false,
tableProps,
tableBtn: [
{
type: 'detail',
btnName: '详情',
},
{
type: 'edit',
btnName: '修改',
},
{
type: 'recover',
btnName: '恢复数据',
showParam: {
type: '&',
data: [
{
type: 'equal', // 改为:等于
name: 'status',
value: 1
},
]
}
},
].filter(v => v),
fileName: '',
formConfig: [
{
type: 'select',
label: '报表类型',
onchange: true,
selectOptions: [
{ id: '1', name: '日' },
{ id: '2', name: '月' },
{ id: '3', name: '年' }
],
param: 'timeDim',
index: 0,
extraOptions: [
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal1',
defaultTime: ['00:00:00', '23:59:59'],
defaultSelect: [],
width: 250,
key: 'datePicker-1', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
},
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
defaultTime: ['00:00:00', '23:59:59'],
defaultSelect: [],
width: 250,
key: 'datePicker-1', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
},
// 日 - 日期范围选择
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'monthrange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeValMonth',
defaultTime: ['00:00:00', '23:59:59'],
width: 250,
key: 'datePicker-2', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
},
// 年 - 单个日期选择(自动获取本年范围)
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'year',
placeholder: '选择年份',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd',
param: 'timeValYear',
width: 250,
key: 'datePicker-3', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
}
]
},
{
type: 'select',
label: '报表类型',
onchange: true,
selectOptions: [
{ id: '0', name: '正常' },
{ id: '1', name: '已修改' },
],
param: 'status',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
}
],
};
},
watch: {
// 监听报表类型变化,强制刷新日期选择器
'listQuery.timeDim'(newVal, oldVal) {
if (newVal !== oldVal && this.$refs.searchBarForm) {
// 触发 search-bar 组件重新渲染(如果 search-bar 支持)
if (this.$refs.searchBarForm.$forceUpdate) {
this.$refs.searchBarForm.$forceUpdate();
}
// 延迟重置定位,确保 DOM 已更新
setTimeout(() => {
const datePickerEl = this.$refs.searchBarForm.$el.querySelector('.el-date-picker');
if (datePickerEl) {
// 触发 Element UI 日期选择器重新计算定位(内部方法)
const datePickerInstance = datePickerEl.__vue__;
if (datePickerInstance && datePickerInstance.updatePopper) {
datePickerInstance.updatePopper();
}
}
}, 100);
}
}
},
mounted() {
// Vue2 中 $refs 需在 $nextTick 中访问(确保 DOM 渲染完成)
this.$nextTick(() => {
if (this.$refs.searchBarForm) {
this.$refs.searchBarForm.formInline.timeDim = '1';
// this.$refs.searchBarForm.formInline.startTime = moment().startOf('day').valueOf();
// this.$refs.searchBarForm.formInline.endTime = moment().endOf('day').valueOf();
}
});
this.listQuery.timeDim = '1';
// this.getDataList();
// console.log('momemt-start',moment().startOf('day').valueOf())
// console.log('momemt-end',moment().endOf('day').valueOf())
},
methods: {
selectType(val) {
// 报表类型切换时的回调(如需扩展可在此添加逻辑)
console.log('报表类型切换:', val);
},
handleClick(val) {
console.log('操作按钮点击:', val);
if (val.type === 'edit') {
this.$router.push({
path: 'cockpitReportEdit',
query: {
id: val.data.id,
edit: true,
timeDim: val.data.timeDim,
time: val.data.time,
}
})
// this.addOrUpdateVisible = true;
// // Vue2 中 $nextTick 确保子组件已渲染
// this.$nextTick(() => {
// this.$refs.addOrUpdate.init(val.data);
// });
} else if (val.type === 'recover') {
recoverDataBackUp({
timeDim:val.data.timeDim,
time: val.data.time,
})
.then(response => {
this.getDataList()
})
.catch(err => {
console.error('恢复数据失败:', err);
// this.tableData = [];
// this.listQuery.total = 0;
})
.finally(() => {
this.dataListLoading = false;
});
} else if (val.type === 'detail') {
this.$router.push({
path: 'cockpitReportEdit',
query: {
id: val.data.id,
edit: false,
timeDim: val.data.timeDim,
time: val.data.time,
}
})
}
},
selectChange(val) {
console.log('选择变更:', val);
this.selectedList = val;
},
buttonClick(val) {
console.log('头部按钮点击:', val);
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
// this.listQuery.bindObjectId = val.bindObjectId ? val.bindObjectId : undefined;
this.listQuery.timeDim = val.timeDim ? val.timeDim : undefined;
this.listQuery.status = val.status ? val.status : undefined;
// 处理不同时间维度的时间范围
this.handleTimeRange(val);
this.getDataList();
break;
case 'export':
this.handleExport();
break;
default:
console.log('未知按钮:', val);
}
},
// 处理不同时间维度的时间范围
handleTimeRange(val) {
const timeDim = val.timeDim;
const timeValDay = val.timeVal;
const timeValMonth = val.timeValMonth;
const timeValYear = val.timeValYear;
// 重置时间参数
this.listQuery.startTime = undefined;
this.listQuery.endTime = undefined;
const getSelectedYearRange = (yearStr) => {
// 解析年份(支持 '2025' 或 '2025-01-01' 格式)
const year = yearStr.includes('-') ? new Date(yearStr).getFullYear() : parseInt(yearStr);
const start = new Date(year, 0, 1); // 本年1月1日 00:00:00
const end = new Date(year, 11, 31, 23, 59, 59); // 本年12月31日 23:59:59
return [start, end];
};
// (可选)如果需要保留格式化字符串的函数,可保留;若仅用时间戳,可删除
// const formatDateTime = (date) => {
// const year = date.getFullYear();
// const month = String(date.getMonth() + 1).padStart(2, '0');
// const day = String(date.getDate()).padStart(2, '0');
// const hours = String(date.getHours()).padStart(2, '0');
// const minutes = String(date.getMinutes()).padStart(2, '0');
// const seconds = String(date.getSeconds()).padStart(2, '0');
// return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
// };
// 核心的switch逻辑修改
switch (timeDim) {
case '1': // 日 - 转换为时间戳
if (timeValDay && timeValDay.length === 2) {
// 字符串转毫秒级时间戳
this.listQuery.startTime = new Date(timeValDay[0]).getTime();
this.listQuery.endTime = new Date(timeValDay[1]).getTime();
// 若需要秒级时间戳使用下面这行除以1000并取整
// this.listQuery.startTime = Math.floor(new Date(timeValDay[0]).getTime() / 1000);
// this.listQuery.endTime = Math.floor(new Date(timeValDay[1]).getTime() / 1000);
}
break;
case '2': // 月 - 转换为时间戳
if (timeValMonth && timeValMonth.length === 2) {
this.listQuery.startTime = new Date(timeValMonth[0]).getTime();
this.listQuery.endTime = new Date(timeValMonth[1]).getTime();
// 秒级时间戳Math.floor(new Date(timeValMonth[0]).getTime() / 1000)
}
break;
case '3': // 年 - 自动计算本年范围并转时间戳
if (timeValYear) {
const [start, end] = getSelectedYearRange(timeValYear);
// 日期对象直接转时间戳
this.listQuery.startTime = start.getTime();
this.listQuery.endTime = end.getTime();
// 秒级时间戳Math.floor(start.getTime() / 1000)
}
break;
}
console.log(this.listQuery);
},
// 获取数据列表
getDataList() {
this.dataListLoading = true;
getDataBackUp(this.listQuery)
.then(response => {
const arr = ['日', '月', '年'];
// Vue2 中数组赋值确保响应式
this.tableData = (response.data?.list || []).map(item => {
item.reportType = arr[item.timeDim-1] || '';
// = this.listQuery.timeDim;
// 匹配产线名称
// const targetLine = this.pdLineList.find(line => line.id === item.bindObjectId);
// item.bindObjectName = targetLine ? targetLine.name : ''
return item;
})
this.listQuery.total = response.data?.total || 0;
})
.catch(err => {
console.error('获取数据失败:', err);
this.tableData = [];
this.listQuery.total = 0;
})
.finally(() => {
this.dataListLoading = false;
});
},
// 每页数变更
sizeChangeHandle(val) {
this.listQuery.pageSize = val;
this.listQuery.pageNo = 1;
this.getDataList();
},
// 当前页变更
currentChangeHandle(val) {
this.listQuery.pageNo = val;
this.getDataList();
},
// 导出处理
handleExport() {
const params = { ...this.listQuery };
// 移除分页参数
// delete params.pageNo;
// delete params.pageSize;
// delete params.total;
this.$modal.confirm('是否确认导出驾驶舱报表?')
.then(() => {
this.exportLoading = true;
return exportDataBackUp(this.listQuery);
})
.then(response => {
this.$download.excel(response, '驾驶舱报表.xls');
})
.catch(err => {
console.error('导出失败:', err);
})
.finally(() => {
this.exportLoading = false;
});
}
},
// Vue2 中监听数据变化(如需)
watch: {
'listQuery.timeDim'(newVal) {
console.log('报表类型变更:', newVal);
// 可添加类型变更后的额外逻辑
}
}
};
</script>
<style scoped>
.app-container {
padding: 16px;
}
.no-data-bg {
height: 400px;
background-color: #f5f7fa;
display: flex;
align-items: center;
justify-content: center;
color: #999;
}
.right-aside {
margin-bottom: 16px;
}
</style>

View File

@@ -1,34 +1,29 @@
<template>
<div class="app-container">
<!-- :isFold="true" 控制展开 -->
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick"
@select-changed="selectType" />
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
<base-table v-if="tableData.length" class="right-aside" v-loading="dataListLoading" :table-props="tableProps"
:page="listQuery.pageNo" :limit="listQuery.pageSize" :table-data="tableData">
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="200" label="操作" :method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<!-- <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList" /> -->
<pagination :limit.sync="listQuery.pageSize" :page.sync="listQuery.pageNo" :total="total" @pagination="getDataList" :background="true" />
</div>
</template>
<script>
// import { parseTime } from '../../mixins/code-filter';
import { getDataBackUp, exportDataBackUp, recoverDataBackUp } from '@/api/cockpit';
// import { exportCostOriginRadioHisData } from '../../../../api/core/monitoring';
import { parseTime } from "@/utils/ruoyi";
import moment from 'moment';
const tableProps = [
{
prop: 'reportType',
label: '报表类型'
},
{
prop: 'time',
prop: 'date',
label: '日期',
width: 160,
filter: parseTime,
// fatter
},
{
prop: 'status',
@@ -37,28 +32,19 @@ const tableProps = [
},
];
export default {
components: {
},
components: {},
data() {
return {
urlOptions: {
// getDataListURL:
},
tableData: [
// {
// reportType: 'reportType',
// status: 'reportType',
// time: '报表类型'
// },
],
urlOptions: {},
tableData: [],
listQuery: {
pageSize: 10,
pageNo: 1,
timeDim: undefined,
timeDim: 2,
startTime: undefined,
endTime: undefined
},
total:0,
pdLineList: [],
exportLoading: false,
dataListLoading: false,
@@ -99,80 +85,23 @@ export default {
type: 'select',
label: '报表类型',
onchange: true,
selectOptions: [
{ id: '1', name: '' },
{ id: '2', name: '月' },
{ id: '3', name: '年' }
],
param: 'timeDim',
index: 0,
extraOptions: [
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal1',
defaultTime: ['00:00:00', '23:59:59'],
defaultSelect: [],
width: 250,
key: 'datePicker-1', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
},
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
defaultTime: ['00:00:00', '23:59:59'],
defaultSelect: [],
width: 250,
key: 'datePicker-1', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
},
// 日 - 日期范围选择
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'monthrange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeValMonth',
defaultTime: ['00:00:00', '23:59:59'],
width: 250,
key: 'datePicker-2', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
},
// 年 - 单个日期选择(自动获取本年范围)
{
parent: 'timeDim',
type: 'datePicker',
label: '统计时间',
dateType: 'year',
placeholder: '选择年份',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd',
param: 'timeValYear',
width: 250,
key: 'datePicker-3', // 唯一 key触发重新渲染
appendToBody: true // 优化定位:挂载到 body 下
}
]
defaultSelect: 0,
selectOptions: [{ id: 0, name: '' }],//1日2月3年
param: 'timeDimF',//目前只有一个维度,所以直接在参数中写死,没有取这个的值
clearable: false,
width: 100,
},
{
type: 'datePicker',
label: '统计时间',
dateType: 'monthrange',
format: 'yyyy-MM',
valueFormat: 'yyyy-MM',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeValMonth',
width: 250
},
{
type: 'select',
@@ -202,43 +131,19 @@ export default {
],
};
},
watch: {
// 监听报表类型变化,强制刷新日期选择器
'listQuery.timeDim'(newVal, oldVal) {
if (newVal !== oldVal && this.$refs.searchBarForm) {
// 触发 search-bar 组件重新渲染(如果 search-bar 支持)
if (this.$refs.searchBarForm.$forceUpdate) {
this.$refs.searchBarForm.$forceUpdate();
}
// 延迟重置定位,确保 DOM 已更新
setTimeout(() => {
const datePickerEl = this.$refs.searchBarForm.$el.querySelector('.el-date-picker');
if (datePickerEl) {
// 触发 Element UI 日期选择器重新计算定位(内部方法)
const datePickerInstance = datePickerEl.__vue__;
if (datePickerInstance && datePickerInstance.updatePopper) {
datePickerInstance.updatePopper();
}
}
}, 100);
}
}
},
mounted() {
// Vue2 中 $refs 需在 $nextTick 中访问(确保 DOM 渲染完成)
this.$nextTick(() => {
if (this.$refs.searchBarForm) {
this.$refs.searchBarForm.formInline.timeDim = '1';
}
});
this.listQuery.timeDim = '1';
// this.getDataList();
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')]
}else{
timeArr = [moment().startOf('month').format('YYYY-MM'), moment().endOf('month').format('YYYY-MM')]
};
this.$refs.searchBarForm.formInline.timeValMonth = timeArr
this.listQuery.startTime = moment(timeArr[0]).startOf('day').valueOf();
this.listQuery.endTime = moment(timeArr[1]).endOf('day').valueOf();
this.getDataList();
},
methods: {
selectType(val) {
// 报表类型切换时的回调(如需扩展可在此添加逻辑)
console.log('报表类型切换:', val);
},
handleClick(val) {
console.log('操作按钮点击:', val);
if (val.type === 'edit') {
@@ -249,13 +154,10 @@ export default {
edit: true,
timeDim: val.data.timeDim,
time: val.data.time,
startTime:this.listQuery.startTime,
endTime:this.listQuery.endTime
}
})
// this.addOrUpdateVisible = true;
// // Vue2 中 $nextTick 确保子组件已渲染
// this.$nextTick(() => {
// this.$refs.addOrUpdate.init(val.data);
// });
} else if (val.type === 'recover') {
recoverDataBackUp({
timeDim:val.data.timeDim,
@@ -266,8 +168,6 @@ export default {
})
.catch(err => {
console.error('恢复数据失败:', err);
// this.tableData = [];
// this.listQuery.total = 0;
})
.finally(() => {
this.dataListLoading = false;
@@ -280,26 +180,24 @@ export default {
edit: false,
timeDim: val.data.timeDim,
time: val.data.time,
startTime:this.listQuery.startTime,
endTime:this.listQuery.endTime
}
})
}
},
selectChange(val) {
console.log('选择变更:', val);
this.selectedList = val;
},
buttonClick(val) {
console.log('头部按钮点击:', val);
if (!val.timeValMonth) {
return this.$modal.msgWarning('请选择统计时间');
}
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
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();
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
// this.listQuery.bindObjectId = val.bindObjectId ? val.bindObjectId : undefined;
this.listQuery.timeDim = val.timeDim ? val.timeDim : undefined;
this.listQuery.status = val.status ? val.status : undefined;
// 处理不同时间维度的时间范围
this.handleTimeRange(val);
this.getDataList();
break;
case 'export':
@@ -309,69 +207,6 @@ export default {
console.log('未知按钮:', val);
}
},
// 处理不同时间维度的时间范围
handleTimeRange(val) {
const timeDim = val.timeDim;
const timeValDay = val.timeVal;
const timeValMonth = val.timeValMonth;
const timeValYear = val.timeValYear;
// 重置时间参数
this.listQuery.startTime = undefined;
this.listQuery.endTime = undefined;
const getSelectedYearRange = (yearStr) => {
// 解析年份(支持 '2025' 或 '2025-01-01' 格式)
const year = yearStr.includes('-') ? new Date(yearStr).getFullYear() : parseInt(yearStr);
const start = new Date(year, 0, 1); // 本年1月1日 00:00:00
const end = new Date(year, 11, 31, 23, 59, 59); // 本年12月31日 23:59:59
return [start, end];
};
// (可选)如果需要保留格式化字符串的函数,可保留;若仅用时间戳,可删除
// const formatDateTime = (date) => {
// const year = date.getFullYear();
// const month = String(date.getMonth() + 1).padStart(2, '0');
// const day = String(date.getDate()).padStart(2, '0');
// const hours = String(date.getHours()).padStart(2, '0');
// const minutes = String(date.getMinutes()).padStart(2, '0');
// const seconds = String(date.getSeconds()).padStart(2, '0');
// return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
// };
// 核心的switch逻辑修改
switch (timeDim) {
case '1': // 日 - 转换为时间戳
if (timeValDay && timeValDay.length === 2) {
// 字符串转毫秒级时间戳
this.listQuery.startTime = new Date(timeValDay[0]).getTime();
this.listQuery.endTime = new Date(timeValDay[1]).getTime();
// 若需要秒级时间戳使用下面这行除以1000并取整
// this.listQuery.startTime = Math.floor(new Date(timeValDay[0]).getTime() / 1000);
// this.listQuery.endTime = Math.floor(new Date(timeValDay[1]).getTime() / 1000);
}
break;
case '2': // 月 - 转换为时间戳
if (timeValMonth && timeValMonth.length === 2) {
this.listQuery.startTime = new Date(timeValMonth[0]).getTime();
this.listQuery.endTime = new Date(timeValMonth[1]).getTime();
// 秒级时间戳Math.floor(new Date(timeValMonth[0]).getTime() / 1000)
}
break;
case '3': // 年 - 自动计算本年范围并转时间戳
if (timeValYear) {
const [start, end] = getSelectedYearRange(timeValYear);
// 日期对象直接转时间戳
this.listQuery.startTime = start.getTime();
this.listQuery.endTime = end.getTime();
// 秒级时间戳Math.floor(start.getTime() / 1000)
}
break;
}
console.log(this.listQuery);
},
// 获取数据列表
getDataList() {
this.dataListLoading = true;
@@ -381,43 +216,22 @@ export default {
// Vue2 中数组赋值确保响应式
this.tableData = (response.data?.list || []).map(item => {
item.reportType = arr[item.timeDim-1] || '';
// = this.listQuery.timeDim;
// 匹配产线名称
// const targetLine = this.pdLineList.find(line => line.id === item.bindObjectId);
// item.bindObjectName = targetLine ? targetLine.name : ''
return item;
})
this.listQuery.total = response.data?.total || 0;
this.total = response.data?.total || 0;
})
.catch(err => {
console.error('获取数据失败:', err);
this.tableData = [];
this.listQuery.total = 0;
this.total = 0;
})
.finally(() => {
this.dataListLoading = false;
});
},
// 每页数变更
sizeChangeHandle(val) {
this.listQuery.pageSize = val;
this.listQuery.pageNo = 1;
this.getDataList();
},
// 当前页变更
currentChangeHandle(val) {
this.listQuery.pageNo = val;
this.getDataList();
},
// 导出处理
handleExport() {
const params = { ...this.listQuery };
// 移除分页参数
// delete params.pageNo;
// delete params.pageSize;
// delete params.total;
this.$modal.confirm('是否确认导出驾驶舱报表?')
.then(() => {
this.exportLoading = true;
@@ -433,13 +247,6 @@ export default {
this.exportLoading = false;
});
}
},
// Vue2 中监听数据变化(如需)
watch: {
'listQuery.timeDim'(newVal) {
console.log('报表类型变更:', newVal);
// 可添加类型变更后的额外逻辑
}
}
};
</script>