You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
638 lines
19 KiB
638 lines
19 KiB
<template> |
|
<basic-container> |
|
<!-- 绩效填报 --> |
|
<avue-crud |
|
:option="option" |
|
:table-loading="loading" |
|
:data="data" |
|
v-model="form" |
|
v-model:page="page" |
|
ref="crud" |
|
@row-update="rowUpdate" |
|
@row-save="rowSave" |
|
@search-change="searchChange" |
|
@search-reset="searchReset" |
|
@selection-change="selectionChange" |
|
@current-change="currentChange" |
|
@size-change="sizeChange" |
|
@refresh-change="refreshChange" |
|
@on-load="onLoad" |
|
@sort-change="sortChange" |
|
> |
|
<template #menu-left> |
|
<el-button |
|
type="primary" |
|
@click="maintenanceContents" |
|
v-if="permission.maintenance_perf_maintenance" |
|
> |
|
绩效内容维护 |
|
</el-button> |
|
</template> |
|
<template #status="scope"> |
|
<el-tag |
|
:type=" |
|
scope.row.status == 1 |
|
? 'warning' |
|
: scope.row.status == 2 || scope.row.status == 4 |
|
? 'success' |
|
: scope.row.status == 3 |
|
? 'info' |
|
: scope.row.status == 5 || scope.row.status == 6 |
|
? 'danger' |
|
: '' |
|
" |
|
> |
|
{{ scope.row.statusName }} |
|
</el-tag> |
|
</template> |
|
<!-- || scope.row.status == 5 --> |
|
<template #menu="scope"> |
|
<el-button |
|
v-if=" |
|
(scope.row.status == 1 && |
|
(scope.row.parentId === 0 || scope.row.parentId === null) && |
|
permission.main_task_download) || |
|
(scope.row.status == 2 && permission.subtask_download) |
|
" |
|
type="text" |
|
@click="downloadTask(scope.row)" |
|
> |
|
下载 |
|
</el-button> |
|
<el-button |
|
v-if=" |
|
((scope.row.parentId === 0 || scope.row.parentId === null) && |
|
scope.row.status == 1 && |
|
permission.main_task_reporting) || |
|
(scope.row.parentId && scope.row.status == 1 && permission.subtask_reporting) || |
|
((scope.row.parentId === 0 || scope.row.parentId === null) && |
|
scope.row.status == 5 && |
|
permission.main_task_reporting) |
|
" |
|
type="text" |
|
@click="fillRow(scope.row)" |
|
> |
|
填报 |
|
</el-button> |
|
<el-button |
|
v-if=" |
|
(scope.row.status == 3 || scope.row.status == 4 || scope.row.status == 5) && |
|
permission.main_task_detail |
|
" |
|
type="text" |
|
@click="detailRow(scope.row)" |
|
> |
|
详情 |
|
</el-button> |
|
<el-button |
|
v-if="scope.row.status == 3 && permission.main_task_examine" |
|
type="text" |
|
@click="examineRow(scope.row)" |
|
> |
|
审批 |
|
</el-button> |
|
<el-button |
|
v-if="scope.row.parentId && scope.row.status == 1 && permission.subtask_delete" |
|
type="text" |
|
@click="removeRow(scope.row)" |
|
> |
|
删除 |
|
</el-button> |
|
<el-button |
|
v-if=" |
|
scope.row.parentId && |
|
scope.row.status == 2 && |
|
scope.row.parentStatus == 1 && |
|
permission.subtask_reset |
|
" |
|
type="text" |
|
@click="resetTaskDetail(scope.row)" |
|
> |
|
重置 |
|
</el-button> |
|
</template> |
|
</avue-crud> |
|
<reportingPerf |
|
v-if="showReport" |
|
:showReport="showReport" |
|
:isDetail="isDetail" |
|
:title="title" |
|
:row="currentRow" |
|
@closeDialog="closeDialog" |
|
></reportingPerf> |
|
<prefDetail |
|
v-if="showDetail" |
|
:showDetail="showDetail" |
|
@closeDetail="closeDetail" |
|
:row="currentRow" |
|
:type="'1'" |
|
/> |
|
<el-dialog append-to-body title="审批" v-model="showExamine" width="85%"> |
|
<!-- 👇 这里全部换成原生 Element UI --> |
|
<el-form :model="examineForm" :rules="rules" ref="examineFormRef" label-width="100px"> |
|
<el-form-item label="审批结果" prop="result"> |
|
<el-radio-group v-model="examineForm.result"> |
|
<el-radio label="1">通过</el-radio> |
|
<el-radio label="2">不通过</el-radio> |
|
</el-radio-group> |
|
</el-form-item> |
|
<el-form-item label="审批意见" prop="remark"> |
|
<el-input |
|
v-model="examineForm.remark" |
|
type="textarea" |
|
:rows="3" |
|
placeholder="请输入审批意见" |
|
></el-input> |
|
</el-form-item> |
|
</el-form> |
|
<template #footer> |
|
<span class="dialog-footer"> |
|
<el-button @click="closeExamine">取 消</el-button> |
|
<el-button type="primary" @click="handleApproval">确 定</el-button> |
|
</span> |
|
</template> |
|
</el-dialog> |
|
<batchAddContent |
|
v-if="showContent" |
|
:showContent="showContent" |
|
:title="title" |
|
@closeDialog="closeDialog" |
|
/> |
|
</basic-container> |
|
</template> |
|
|
|
<script> |
|
import { mapGetters } from 'vuex'; |
|
import reportingPerf from './components/reportingPerf.vue'; |
|
import prefDetail from './components/prefDetail.vue'; |
|
import batchAddContent from './components/batchAddContent.vue'; |
|
import { |
|
pageBsEfficiencyTask, |
|
approvalBsEfficiencyTask, |
|
rejectBsEfficiencyTask, |
|
removeBsEfficiencyTask, |
|
subResetBsEfficiencyTask, |
|
downloadBsEfficiencyTaskTemplate, |
|
} from '@/api/performanceManagement/dataReporting'; |
|
import { downloadXls, downloadFile, downloadFileBlob } from '@/utils/util'; |
|
import { saveAs } from 'file-saver'; |
|
import JSZip from 'jszip'; |
|
export default { |
|
components: { reportingPerf, prefDetail, batchAddContent }, |
|
data() { |
|
return { |
|
showDialog: false, |
|
typeValue: '1', |
|
resultValue: '', |
|
showReport: false, |
|
isDetail: false, |
|
title: '', |
|
showContent: false, |
|
currentRow: null, |
|
showDetail: false, |
|
showExamine: false, |
|
examineForm: { |
|
result: '1', |
|
remark: '', |
|
}, |
|
rules: { |
|
result: [{ required: true, message: '请选择审批结果', trigger: 'change' }], |
|
}, |
|
loading: false, |
|
data: [], |
|
form: {}, |
|
page: { |
|
pageSize: 10, |
|
currentPage: 1, |
|
total: 0, |
|
}, |
|
query: {}, |
|
option: { |
|
height: 'auto', |
|
align: 'center', |
|
calcHeight: 32, |
|
rowKey: 'id', |
|
rowParentKey: 'parentId', |
|
tip: false, |
|
simplePage: true, |
|
searchShow: true, |
|
searchMenuSpan: 12, |
|
searchIcon: true, |
|
searchIndex: 3, |
|
tree: true, |
|
treeProps: { |
|
children: 'subTasks', |
|
hasChildren: 'hasChildren', |
|
}, |
|
border: true, |
|
index: false, |
|
selection: false, |
|
viewBtn: false, |
|
delBtn: false, |
|
addBtn: false, |
|
editBtn: false, |
|
editBtnText: '修改', |
|
addBtnIcon: ' ', |
|
viewBtnIcon: ' ', |
|
delBtnIcon: ' ', |
|
editBtnIcon: ' ', |
|
viewBtnText: '详情', |
|
menu: true, |
|
menuWidth: 150, |
|
dialogWidth: 1200, |
|
dialogClickModal: false, |
|
searchEnter: true, |
|
excelBtn: false, |
|
filterBtn: true, |
|
searchShowBtn: false, |
|
columnSort: true, |
|
excelBtn: true, |
|
columnSort: true, |
|
showOverflowTooltip: true, |
|
searchLabelPosition: 'left', |
|
searchGutter: 24, |
|
searchSpan: 6, |
|
menuAlign: 'center', |
|
gridBtn: false, |
|
searchMenuPosition: 'right', |
|
labelWidth: 120, |
|
searchLabelWidth: 'auto', |
|
column: [ |
|
{ |
|
label: '任务名称', |
|
prop: 'taskName', |
|
search: true, |
|
sortable: 'custom', |
|
overHidden: true, |
|
align: 'left', |
|
headerAlign: 'center', |
|
}, |
|
{ |
|
label: '绩效填报人', |
|
prop: 'reportUserName', |
|
search: true, |
|
sortable: 'custom', |
|
overHidden: true, |
|
width: 110, |
|
}, |
|
{ |
|
label: '状态', |
|
prop: 'status', |
|
type: 'select', |
|
search: false, |
|
sortable: 'custom', |
|
overHidden: true, |
|
width: 100, |
|
dicData: [ |
|
{ label: '进行中', value: 1, type: 'warning' }, // 橙色 - 处理中 |
|
{ label: '已完成', value: 2, type: 'success' }, // 绿色 - 成功完成 |
|
{ label: '待审批', value: 3, type: 'info' }, // 灰色 - 等待状态 |
|
{ label: '审批通过', value: 4, type: 'success' }, // 绿色 - 成功 |
|
{ label: '审批不通过', value: 5, type: 'danger' }, // 红色 - 失败/拒绝 |
|
{ label: '已超期', value: 6, type: 'danger' }, // 红色 - 失败/拒绝 |
|
{ label: '任务失败', value: 7, type: 'danger' }, |
|
], |
|
}, |
|
{ |
|
label: '下发人', |
|
prop: 'createUserName', |
|
search: false, |
|
sortable: 'custom', |
|
overHidden: true, |
|
width: 100, |
|
}, |
|
{ |
|
label: '下发时间', |
|
prop: 'createTime', |
|
search: false, |
|
sortable: 'custom', |
|
overHidden: true, |
|
width: 150, |
|
}, |
|
{ |
|
label: '填报时间', |
|
prop: 'reportTime', |
|
search: false, |
|
sortable: 'custom', |
|
overHidden: true, |
|
width: 150, |
|
}, |
|
], |
|
}, |
|
}; |
|
}, |
|
mounted() {}, |
|
methods: { |
|
maintenanceContents() { |
|
this.title = '模板内容维护'; |
|
this.showContent = true; |
|
}, |
|
// 填报 |
|
fillRow(row) { |
|
if (row.parentId !== 0) { |
|
const currentUser = this.$store.state.user.userInfo; |
|
if (currentUser && currentUser.account !== row.reportUserName) { |
|
this.$message.error( |
|
row.parentId == 0 ? '无权限填报任务明细填报!' : '无权限填报任务填报!' |
|
); |
|
return; |
|
} |
|
} |
|
this.currentRow = row; |
|
this.title = row.parentId !== 0 ? '任务明细填报' : '任务填报'; |
|
this.isDetail = row.parentId !== 0 ? true : false; |
|
this.showReport = true; |
|
}, |
|
closeDialog(val) { |
|
this.showReport = false; |
|
this.isDetail = false; |
|
this.showDetail = false; |
|
this.showContent = false; |
|
|
|
if (val) { |
|
this.onLoad(); |
|
} |
|
}, |
|
closeDetail(val) { |
|
this.showDetail = false; |
|
}, |
|
detailRow(row) { |
|
this.currentRow = row; |
|
this.showDetail = true; |
|
}, |
|
// 汇总 |
|
collectRow(row) { |
|
this.$confirm('确定汇总当前绩效?', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
}).then(res => {}); |
|
}, |
|
// 审批 |
|
examineRow(row) { |
|
this.examineForm = { |
|
result: '1', |
|
remark: '', |
|
}; |
|
this.currentRow = row; |
|
this.showExamine = true; |
|
}, |
|
// 任务行下载模板 → 打包ZIP |
|
async downloadTask(row) { |
|
const zip = new JSZip(); |
|
const promises = []; // 存储下载Promise |
|
if (row.parentId == 0) { |
|
if (!row.subTasks || row.subTasks.length === 0) { |
|
this.$message.warning('暂无可下载文件!'); |
|
return; |
|
} |
|
// 只下载状态为2(已完成)的任务 |
|
const completedTasks = row.subTasks.filter(task => task.status === 2); |
|
if (completedTasks.length === 0) { |
|
this.$message.warning('暂无可下载文件!'); |
|
return; |
|
} |
|
try { |
|
// 1. 下载模板文件并加入压缩包 |
|
const templateRes = await downloadBsEfficiencyTaskTemplate(); |
|
zip.file(`${row.yearMonth}绩效填报模板.xlsx`, templateRes.data); |
|
// 2. 下载所有已完成的子任务附件 |
|
completedTasks.forEach(task => { |
|
if (task.attachLink) { |
|
const promise = fetch(task.attachLink) |
|
.then(res => res.blob()) |
|
.then(blob => { |
|
zip.file(`${task.taskName}.xlsx`, blob); |
|
}); |
|
promises.push(promise); |
|
} |
|
}); |
|
// 等待所有文件下载完成 → 生成zip并下载 |
|
await Promise.all(promises); |
|
const content = await zip.generateAsync({ type: 'blob' }); |
|
saveAs(content, `${row.yearMonth}绩效填报文件包.zip`); |
|
this.$message.success('打包下载成功'); |
|
} catch (error) { |
|
console.error('打包下载失败:', error); |
|
this.$message.error('打包下载失败,请稍后重试'); |
|
} |
|
} else { |
|
// 子任务 → 单文件打包成zip |
|
// if (!row.attachLink) { |
|
// this.$message.warning('暂无可下载文件!'); |
|
// return; |
|
// } |
|
// try { |
|
// const res = await fetch(row.attachLink); |
|
// const blob = await res.blob(); |
|
// zip.file(`${row.taskName}.xlsx`, blob); |
|
|
|
// const content = await zip.generateAsync({ type: 'blob' }); |
|
// saveAs(content, `${row.taskName}.zip`); |
|
// this.$message.success('打包下载成功'); |
|
// } catch (error) { |
|
// console.error('下载失败:', error); |
|
// this.$message.error('文件下载失败'); |
|
// } |
|
if (row.attachLink == '') { |
|
this.$message.warning('暂无可下载文件!'); |
|
return; |
|
} |
|
downloadFileBlob(row.attachLink, row.taskName + '.xlsx'); |
|
} |
|
}, |
|
// 任务明细行重置 |
|
resetTaskDetail(row) { |
|
this.$confirm( |
|
'确定重置当前任务明细?重置后状态将变更为【进行中】,之前上传的文件将被作废。', |
|
{ |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
} |
|
).then(() => { |
|
subResetBsEfficiencyTask({ id: row.id }).then(res => { |
|
if (res.data.code === 200) { |
|
this.$message.success('重置成功'); |
|
this.onLoad(); |
|
} else { |
|
this.$message.error('重置失败'); |
|
} |
|
}); |
|
}); |
|
}, |
|
// 关闭审批弹框 |
|
closeExamine() { |
|
this.showExamine = false; |
|
// 重置表单数据 |
|
this.examineForm = { |
|
result: '', |
|
remark: '', |
|
}; |
|
}, |
|
// 处理审批 |
|
handleApproval() { |
|
if (!this.currentRow) return; |
|
// 表单验证 |
|
this.$refs.examineFormRef.validate(valid => { |
|
if (valid) { |
|
if (this.examineForm.result === '1') { |
|
this.approvalRow(this.currentRow); |
|
} else if (this.examineForm.result === '2') { |
|
this.rejectRow(this.currentRow); |
|
} |
|
} |
|
}); |
|
}, |
|
// 删除 |
|
removeRow(row) { |
|
this.$confirm('确定删除当前绩效任务明细?', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
}).then(() => { |
|
removeBsEfficiencyTask({ ids: row.id }).then(res => { |
|
if (res.data.code === 200) { |
|
this.$message.success('删除成功'); |
|
this.onLoad(); |
|
} else { |
|
this.$message.error('删除失败'); |
|
} |
|
}); |
|
}); |
|
}, |
|
// 审批通过 |
|
approvalRow(row) { |
|
this.$confirm('确定审批通过当前绩效任务?', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'success', |
|
}).then(() => { |
|
approvalBsEfficiencyTask({ id: row.id, remark: this.examineForm.remark }).then(res => { |
|
if (res.data.code === 200) { |
|
this.$message.success('审批通过成功'); |
|
this.closeExamine(); |
|
this.onLoad(); |
|
} else { |
|
this.$message.error('审批通过失败'); |
|
} |
|
}); |
|
}); |
|
}, |
|
// 审批不通过 |
|
rejectRow(row) { |
|
this.$confirm('确定审批不通过当前绩效任务?', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
}).then(() => { |
|
rejectBsEfficiencyTask({ id: row.id, remark: this.examineForm.remark }).then(res => { |
|
if (res.data.code === 200) { |
|
this.$message.success('审批不通过成功'); |
|
this.closeExamine(); |
|
this.onLoad(); |
|
} else { |
|
this.$message.error('审批不通过失败'); |
|
} |
|
}); |
|
}); |
|
}, |
|
// 表格排序 |
|
sortChange({ prop, order }) { |
|
if (!prop) { |
|
// 如果取消排序,清空排序参数 |
|
this.query.orderByField = undefined; |
|
this.query.asc = undefined; |
|
} else { |
|
const orderByField = prop.replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase(); |
|
this.query.orderByField = |
|
orderByField == 'REPORT_USER_NAME' |
|
? 'bu.real_name' |
|
: orderByField == 'STATUS' |
|
? 't.STATUS' |
|
: orderByField == 'CREATE_USER_NAME' |
|
? 'bu1.real_name' |
|
: orderByField == 'CREATE_TIME' |
|
? 't.CREATE_TIME' |
|
: orderByField; |
|
this.query.asc = order === 'ascending' ? true : false; |
|
} |
|
// 重新加载数据 |
|
this.onLoad(); |
|
}, |
|
onLoad() { |
|
this.loading = true; |
|
const params = { |
|
pageSize: this.page.pageSize, |
|
currentPage: this.page.currentPage, |
|
...this.query, |
|
}; |
|
console.log(params); |
|
pageBsEfficiencyTask(params) |
|
.then(res => { |
|
if (res.data.code === 200) { |
|
// 为子任务添加父级状态 |
|
const processTasks = tasks => { |
|
return tasks.map(task => { |
|
if (task.subTasks && task.subTasks.length > 0) { |
|
// 为每个子任务添加父级状态 |
|
task.subTasks = task.subTasks.map(subTask => ({ |
|
...subTask, |
|
parentStatus: task.status, // 添加父级状态 |
|
})); |
|
// 递归处理子任务的子任务 |
|
processTasks(task.subTasks); |
|
} |
|
return task; |
|
}); |
|
}; |
|
this.data = processTasks(res.data.data.records || []); |
|
this.page.total = res.data.data.total || 0; |
|
} else { |
|
this.data = []; |
|
this.page.total = 0; |
|
} |
|
this.loading = false; |
|
}) |
|
.catch(() => { |
|
this.data = []; |
|
this.page.total = 0; |
|
this.loading = false; |
|
}); |
|
}, |
|
currentChange(currentPage) { |
|
this.page.currentPage = currentPage; |
|
}, |
|
sizeChange(pageSize) { |
|
this.page.pageSize = pageSize; |
|
}, |
|
refreshChange() { |
|
this.onLoad(this.page, this.query); |
|
}, |
|
searchReset() { |
|
this.query = {}; |
|
this.treeDeptId = ''; |
|
this.onLoad(this.page); |
|
}, |
|
searchChange(params, done) { |
|
this.query = params; |
|
this.page.currentPage = 1; |
|
this.onLoad(this.page, params); |
|
done(); |
|
}, |
|
}, |
|
computed: { |
|
...mapGetters(['userInfo', 'permission']), |
|
permissionList() { |
|
return { |
|
addBtn: true, |
|
viewBtn: true, |
|
delBtn: true, |
|
editBtn: true, |
|
}; |
|
}, |
|
}, |
|
}; |
|
</script> |
|
|
|
<style></style>
|
|
|