预算&指标填报

This commit is contained in:
2026-03-05 11:12:34 +08:00
parent babbe98c09
commit 2f3586e2f2
15 changed files with 537 additions and 371 deletions

View File

@@ -22,7 +22,7 @@
</el-form-item>
<el-form-item>
<el-button style="background-color: #0B58FF;" type="primary" @click="onSubmit">查询</el-button>
<!-- <el-button type="primary" plain size="medium">导入</el-button> -->
<el-button type="primary" plain size="medium" @click='importExcel'>导入</el-button>
</el-form-item>
</el-form>
</div>
@@ -35,14 +35,14 @@
<div v-if="!isDetail" style="display: flex;gap: 8px;align-items: center;height: 32px;">
<div style="width: 4px;height: 16px;background: #0B58FF;border-radius: 1px;"></div>
<div style="width: 58px;
height: 16px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: rgba(0,0,0,0.85);
line-height: 16px;
text-align: right;
font-style: normal;">指标详情</div>
height: 16px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: rgba(0,0,0,0.85);
line-height: 16px;
text-align: right;
font-style: normal;">指标详情</div>
<el-button style="background-color: #0B58FF;height: 32px;line-height: 10px;" type="primary"
@click="handleEdit">编辑</el-button>
</div>
@@ -53,12 +53,12 @@ font-style: normal;">指标详情</div>
<div
style="width: 58px;height: 16px;font-family: PingFangSC, PingFang SC;font-weight: 400;font-size: 14px;color: rgba(0,0,0,0.85);line-height: 16px;text-align: right;font-style: normal;">
快捷操作</div>
<!-- <el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
@click="onSubmit">复制上月</el-button>
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
@click="onSubmit">全部上调5%</el-button>
@click="copyLastMonth">复制上月/</el-button>
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
@click="onSubmit">全部调5%</el-button> -->
@click="allUp">全部调5%</el-button>
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
@click="allDown">全部下调5%</el-button>
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
@click="handleClear">清空配置</el-button>
<el-button style="background-color: #0B58FF;height: 32px;line-height: 10px;" type="primary"
@@ -69,24 +69,24 @@ font-style: normal;">指标详情</div>
<!-- 表格组件添加key属性强制刷新绑定所有必要属性 -->
<base-table style="height: 700px;" :maxHeight=" '700' " @emitFun="inputChange" class="right-aside"
:table-props="tableProps" :page="form.pageNo" :limit="form.pageSize" :table-data="tableData" ref="baseTable"
:key="`base-table-${isDetail}-${timeType}`"></base-table>
:table-props="tableProps" :page="form.pageNo" :limit="form.pageSize" :table-data="tableData" ref="baseTable" id='calendarTable'
:key="tableKey"></base-table>
</div>
</div>
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" action="#" :disabled="upload.isUploading"
:on-change="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
@click="importTemplate">下载模板</el-link>
</div>
<div class="el-upload__tip" slot="tip">
<el-radio-group v-model="upload.timeDim">
<el-radio :label="2">月预算</el-radio>
<el-radio :label="3">年预算</el-radio>
</el-radio-group>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
@@ -99,9 +99,11 @@ font-style: normal;">指标详情</div>
<script>
import Container from './container.vue'
import { getLevelStruc, getTargetMonthPage, updateTargetMonthData, getTargetYearPage, updateTargetYearData, getDictListData } from '@/api/cockpit'
import { getLevelStruc, getTargetMonthPage, updateTargetMonthData, getTargetYearPage, updateTargetYearData,copyLastMonthData, copyLastYearData} from '@/api/cockpit'
import inputArea from './inputArea.vue' // 导入输入组件
import { getBaseHeader } from "@/utils/request";
import { publicFormatter } from '@/utils/dict';
import {getAccessToken, getTenantId} from '@/utils/auth'
import axios from 'axios';
export default {
name: 'ProductionStatus',
components: {
@@ -118,34 +120,33 @@ export default {
data() {
return {
form: {
levelId: 1,
levelId: undefined,
pageNo: 1,
pageSize: 100,
date: undefined, // 统一存储日期(月份/年份)
startTime: undefined, // 起始时间戳
endTime: undefined // 结束时间戳
},
dictData: [],
upload: {
// 是否显示弹出层(用户导入)
// 是否显示弹出层
open: false,
// 弹出层标题(用户导入)
title: "",
// 弹出层标题
title: "预算填报导入",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: getBaseHeader(),
// 上传的地址
url: process.env.VUE_APP_BASE_API + '/admin-api/system/user/import'
fileList:[],
currentFile:null,
timeDim: 2
},
getDataList: null, // 动态切换的查询接口
updateData: null, // 动态切换的更新接口
isDetail: false, // 编辑状态标识false=只读true=编辑
tableData: [], // 表格数据
levelLList: [], // 所属层级下拉数据
tableProps: [] // 表格列配置
tableProps: [], // 表格列配置
tableKey:0,// 强制表格更新
allUpBtn: false, // 全部上调按钮状态
allDownBtn: false // 全部下调按钮状态
}
},
watch: {
@@ -182,7 +183,6 @@ export default {
this.initDefaultDate();
// 2. 计算对应时间戳
this.calculateTimeStamp();
this.getDictData()
// 3. 先初始化表格配置(优先于数据请求,避免表格空配置渲染)
this.initTableProps(this.isDetail);
// 4. 等待配置就绪后,再请求数据,避免异步冲突
@@ -191,70 +191,119 @@ export default {
});
},
methods: {
getDictData() {
getDictListData({ pageNo: 1, pageSize: 100, dictType: 'lb_dw' }).then((res) => {
this.dictData = res.data.list
// 清空配置
handleClear() {
// 清空target
this.tableData.forEach(item => {
item.target = null;
})
this.tableKey++;
this.allDownBtn = false;
this.allUpBtn = false;
},
// 表格单元格数据变更回调
inputChange(val) {
console.log('修改的数据:', val);
// 安全修改:判断索引是否存在,避免数组越界
if (this.tableData[val._pageIndex - 1]) {
this.tableData[val._pageIndex - 1][val.prop] = val[val.prop];
// 标记数据为已修改状态
this.tableData[val._pageIndex - 1].status = 1;
//复制上月/上年数据(调用接口不同)
copyLastMonth() {
if(this.timeType === 'month') {
this.$modal.confirm('是否确认复制上月数据?').then(() => {
this.copyLastMonthDataPage()
}).then(() => {
this.$modal.msgSuccess("复制成功");
}).catch(() => { });
}else{
this.$modal.confirm('是否确认复制上年数据?').then(() => {
this.copyLastYearDataPage()
}).then(() => {
this.$modal.msgSuccess("复制成功");
}).catch(() => { });
}
},
// 初始化表格列配置核心精准控制inputArea挂载
initTableProps(isEdit) {
console.log('当前编辑状态:', isEdit, '当前时间维度:', this.timeType);
// 基础表格列配置(只读模式使用)
const baseTableProps = [
{ prop: 'type', label: '指标类型', align: 'center' },
{ prop: 'name', label: '指标名称', align: 'center' },
{ prop: 'unit', label: '单位', align: 'center' },
{ prop: 'target', label: '预估值', align: 'center' },
];
if (isEdit) {
// 编辑模式仅给「预估值」列添加inputArea精准挂载避免无效配置
this.tableProps = baseTableProps.map(item => {
if (item.prop === 'target') { // 只给需要编辑的列添加子组件
return {
...item,
subcomponent: inputArea // 挂载输入组件
};
}
return item; // 其他列保持原有配置
copyLastMonthDataPage() {
copyLastMonthData({
levelId: this.form.levelId,
startTime: this.form.startTime,
endTime: this.form.endTime,
pageSize: this.form.pageSize,
pageNo: this.form.pageNo
}).then((res) => {
this.tableData = res.data.map(item => {
// 新增unitLabel字段存储匹配后的显示名称
return {
...item
};
});
} else {
// 只读模式:深拷贝基础配置,避免引用污染
this.tableProps = JSON.parse(JSON.stringify(baseTableProps));
}
console.log('表格配置:', this.tableProps);
this.tableKey++;
this.allDownBtn = false;
this.allUpBtn = false;
}).catch(err => {
console.error('获取表格数据失败:', err);
this.tableData = [];
});
},
copyLastYearDataPage() {
copyLastYearData({
levelId: this.form.levelId,
startTime: this.form.startTime,
endTime: this.form.endTime,
pageSize: this.form.pageSize,
pageNo: this.form.pageNo
}).then((res) => {
this.tableData = res.data.map(item => {
// 新增unitLabel字段存储匹配后的显示名称
return {
...item
};
});
this.tableKey++;
this.allDownBtn = false;
this.allUpBtn = false;
}).catch(err => {
console.error('获取表格数据失败:', err);
this.tableData = [];
});
},
//全部上调5%
allUp() {
if(this.allUpBtn || this.allDownBtn) {
this.$modal.msgWarning("数据已调整,请先保存数据");
return
}
for(let i = 0; i < this.tableData.length; i++) {
this.tableData[i].target = (this.tableData[i].target * 1.05).toFixed(2)
}
// 强制表格组件刷新
this.tableKey++;
this.allUpBtn = true;
},
// 全部下调5%
allDown() {
if(this.allUpBtn || this.allDownBtn) {
this.$modal.msgWarning("数据已调整,请先保存数据");
return;
}
for(let i = 0; i < this.tableData.length; i++) {
this.tableData[i].target = (this.tableData[i].target * 0.95).toFixed(2)
}
// 强制表格组件刷新
this.tableKey++;
this.allDownBtn = true;
},
// 查询按钮
onSubmit() {
// 清空原有表格数据,重新请求
this.tableData = [];
this.$nextTick(() => {
this.getDataPage();
});
},
// 切换到编辑模式
handleEdit() {
this.isDetail = true;
// 先更新表格配置,再强制表格刷新(双重保障)
// 先更新表格配置,再强制表格刷新
this.initTableProps(this.isDetail);
this.$nextTick(() => {
if (this.$refs.baseTable) {
this.$refs.baseTable.$forceUpdate(); // 强制表格组件刷新
}
});
this.tableKey++;
},
// 保存数据使用动态切换的updateData接口
handleSave() {
// if (!this.updateData) {
// this.$modal.msgWarning('当前时间维度异常,无法保存');
// return;
// }
this.$modal.confirm('是否确认保存数据?').then(() => {
return this.updateData(this.tableData)
}).then(() => {
@@ -269,23 +318,58 @@ export default {
this.$modal.msgSuccess("保存成功");
}).catch(() => { });
},
// 请求下拉数据和表格数据使用动态切换的getDataList接口
getData() {
if (!this.getDataList) {
console.warn('当前时间维度异常,无法获取数据');
return;
}
// 1. 请求所属层级下拉数据
getLevelStruc().then((res) => {
this.levelLList = res.data || [];
this.form.levelId = this.levelLList[0].id;
this.getDataPage()
}).catch(err => {
console.error('获取所属层级失败:', err);
this.levelLList = [];
});
this.$emit('updateLeft')
},
getDataPage() {
// 2. 请求表格分页数据(使用动态接口)
this.getDataList({
levelId: this.form.levelId,
startTime: this.form.startTime,
endTime: this.form.endTime,
pageSize: this.form.pageSize,
pageNo: this.form.pageNo
}).then((res) => {
console.log('表格数据:', res);
this.tableData = res.data.map(item => {
// 新增unitLabel字段存储匹配后的显示名称
return {
...item
};
});
}).catch(err => {
console.error('获取表格数据失败:', err);
this.tableData = [];
});
},
// 表格单元格数据变更回调
inputChange(val) {
// 安全修改:判断索引是否存在,避免数组越界
if (this.tableData[val._pageIndex - 1]) {
this.tableData[val._pageIndex - 1][val.prop] = val[val.prop];
// 标记数据为已修改状态
this.tableData[val._pageIndex - 1].status = 1;
}
},
// 取消编辑,恢复只读模式
handleCancel() {
this.isDetail = false;
// 重置表格配置
this.initTableProps(this.isDetail);
// 清空并重新请求数据,恢复原始状态
this.$nextTick(() => {
this.tableData = [];
this.getData();
});
console.log('已取消编辑,恢复原始数据');
},
// 清空配置
handleClear() {
this.isDetail = false;
this.allUpBtn = false;
this.allDownBtn = false;
// 重置表格配置
this.initTableProps(this.isDetail);
// 清空并重新请求数据,恢复原始状态
@@ -294,13 +378,39 @@ export default {
this.getData();
});
},
// 初始化表格列配置核心精准控制inputArea挂载
initTableProps(isEdit) {
console.log('当前编辑状态:', isEdit, '当前时间维度:', this.timeType);
// 基础表格列配置(只读模式使用)
const baseTableProps = [
{ prop: 'type', label: '指标类型', align: 'center' },
{ prop: 'name', label: '指标名称', align: 'center' },
{ prop: 'unit', label: '单位', align: 'center', filter: publicFormatter('lb_dw') },
{ prop: 'target', label: '预估值', align: 'center' },
];
if (isEdit) {
// 编辑模式仅给「预估值」列添加inputArea精准挂载避免无效配置
this.tableProps = baseTableProps.map(item => {
if (item.prop === 'target') { // 只给需要编辑的列添加子组件
return {
...item,
subcomponent: inputArea // 挂载输入组件
};
}
return item; // 其他列保持原有配置
});
} else {
// 只读模式:深拷贝基础配置,避免引用污染
// this.tableProps = JSON.parse(JSON.stringify(baseTableProps));
this.tableProps = baseTableProps;
}
console.log('表格配置:', this.tableProps);
},
// 初始化默认日期根据timeType
initDefaultDate() {
const currentDate = new Date();
this.form.date = currentDate;
},
// 计算时间戳根据timeType切换月/年)
calculateTimeStamp(selectDate) {
let targetDate = selectDate || this.form.date;
@@ -330,7 +440,6 @@ export default {
this.form.endTime = endDatePrecise.getTime();
}
},
// 日期选择器变更事件(统一处理月/年变更)
handleDateChange(val) {
if (!val) {
@@ -342,62 +451,61 @@ export default {
// 计算选中日期对应的时间戳
this.calculateTimeStamp(val);
},
getUnitLabel(unitCode) {
// 若字典为空或无匹配编码,返回原编码或空字符串
if (!this.dictData || this.dictData.length === 0) {
return unitCode || '';
}
// 查找匹配的字典项
const matchItem = this.dictData.find(item => item.value == unitCode);
// 返回匹配的label无匹配则返回原unit编码
return matchItem ? matchItem.label : (unitCode || '');
// 导入
importExcel() {
this.upload.open = true
},
// 请求下拉数据和表格数据使用动态切换的getDataList接口
getData() {
if (!this.getDataList) {
console.warn('当前时间维度异常,无法获取数据');
return;
}
// 1. 请求所属层级下拉数据
getLevelStruc().then((res) => {
console.log('所属层级数据:', res);
this.levelLList = res.data || [];
}).catch(err => {
console.error('获取所属层级失败:', err);
this.levelLList = [];
});
// 2. 请求表格分页数据(使用动态接口)
this.getDataList({
levelId: this.form.levelId,
startTime: this.form.startTime,
endTime: this.form.endTime,
pageSize: this.form.pageSize,
pageNo: this.form.pageNo
}).then((res) => {
console.log('表格数据:', res);
this.tableData = res.data.map(item => {
// 新增unitLabel字段存储匹配后的显示名称
return {
...item,
unitLabel: this.getUnitLabel(item.unit)
};
});
}).catch(err => {
console.error('获取表格数据失败:', err);
this.tableData = [];
});
// 文件上传中处理
handleFileUploadProgress(file, fileList) {
console.log('文件上传中:',file, fileList)
this.upload.isUploading = true;
this.upload.fileList = fileList;
this.upload.currentFile = file.raw;
},
handleFileSuccess() {},
importTemplate() {},
// 提交上传文件
async submitFileForm() {
try {
if (!this.upload.currentFile) {
return this.$message.error('请先选择要上传的文件!')
}
const formData = new FormData()
formData.append('file', this.upload.currentFile) // 文件字段
formData.append('timeDim', this.upload.timeDim) // 年月维度字段
formData.append('reportDate', this.form.endTime) // 时间维度字段
formData.append('levelId', this.form.levelId) // 层级维度字段
const response = await axios({
url: process.env.VUE_APP_BASE_API + '/admin-api/lb/index-target-month/import',
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': "Bearer " + getAccessToken(),
'tenant-id': getTenantId(),
},
timeout: 30000
})
// 4. 处理响应结果
if (response.data.code === 0) {
this.$message.success('文件上传成功!')
// 重置表单
this.upload.fileList = []
this.upload.timeDim = 2
this.upload.currentFile = null
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles();
this.getData()
} else {
this.$message.error(`上传失败:${response.data.msg || '未知错误'}`)
}
} catch (error) {
// 5. 异常处理
console.error('文件上传出错:', error)
this.$message.error('上传失败!')
}
},
// 查询按钮点击事件(可根据需求扩展逻辑)
onSubmit() {
// 清空原有表格数据,重新请求
this.tableData = [];
this.$nextTick(() => {
this.getData();
});
}
}
}
</script>