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.
256 lines
8.3 KiB
256 lines
8.3 KiB
<template> |
|
<div class="hazard-audit-page"> |
|
<el-page-header content="隐患审核" class="page-header" @back="goBack" /> |
|
|
|
<el-alert |
|
v-if="routeError" |
|
:title="routeError" |
|
type="warning" |
|
:closable="false" |
|
show-icon |
|
class="route-alert" |
|
/> |
|
|
|
<div v-else v-loading="loading" class="audit-content"> |
|
<el-alert |
|
v-if="loadError" |
|
:title="loadError" |
|
type="error" |
|
:closable="false" |
|
show-icon |
|
class="route-alert" |
|
> |
|
<el-button slot="default" type="text" @click="loadPage">重新加载</el-button> |
|
</el-alert> |
|
|
|
<template v-else-if="loaded"> |
|
<el-alert |
|
v-if="!taskId" |
|
title="当前未获取到任务 ID,仅可查看详情,无法执行审批。" |
|
type="warning" |
|
:closable="false" |
|
show-icon |
|
class="route-alert" |
|
style="grid-column: 1 / -1;" |
|
/> |
|
<hazard-report-panel :report="report" :attachments="attachments" /> |
|
<audit-action-form |
|
:report="report" |
|
:report-id="reportId" |
|
:attachments="attachments" |
|
:task-id="taskId" |
|
:submitting="submitting" |
|
@upload="handleAttachmentUpload" |
|
@submit="handleAuditSubmit" |
|
@switch-level="handleSwitchLevel" |
|
@estimated-points="estimatedPoints = $event" |
|
/> |
|
<flow-sync-panel :report="report" :estimated-points="estimatedPoints" /> |
|
</template> |
|
</div> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
import HazardReportPanel from './components/HazardReportPanel' |
|
import AuditActionForm from './components/AuditActionForm' |
|
import FlowSyncPanel from './components/FlowSyncPanel' |
|
import { |
|
completeHazardAudit, |
|
getHazardAuditDetail, |
|
getHazardProcessDetail, |
|
listHazardAttachments, |
|
switchHazardLevel, |
|
updateHazardReport, |
|
uploadHazardAttachment |
|
} from '@/api/hazard/audit' |
|
|
|
export default { |
|
name: 'HazardAudit', |
|
components: { HazardReportPanel, AuditActionForm, FlowSyncPanel }, |
|
data() { |
|
return { |
|
loading: false, |
|
submitting: false, |
|
loaded: false, |
|
loadError: '', |
|
report: {}, |
|
taskId: '', |
|
attachments: [], |
|
estimatedPoints: null |
|
} |
|
}, |
|
computed: { |
|
reportId() { |
|
return String(this.$route.query.id || '') |
|
}, |
|
routeError() { |
|
if (!this.reportId) return '缺少隐患 ID,无法加载审核详情。' |
|
return '' |
|
} |
|
}, |
|
watch: { |
|
'$route.query': { |
|
immediate: true, |
|
deep: true, |
|
handler() { |
|
if (this.routeError) { |
|
this.resetPage() |
|
return |
|
} |
|
this.loadPage() |
|
} |
|
} |
|
}, |
|
methods: { |
|
resetPage() { |
|
this.loading = false |
|
this.loaded = false |
|
this.loadError = '' |
|
this.report = {} |
|
this.taskId = '' |
|
this.attachments = [] |
|
this.estimatedPoints = null |
|
}, |
|
async loadPage() { |
|
this.loading = true |
|
this.loaded = false |
|
this.loadError = '' |
|
try { |
|
const results = await Promise.all([ |
|
getHazardAuditDetail(this.reportId), |
|
listHazardAttachments(this.reportId) |
|
]) |
|
this.report = results[0].data || {} |
|
this.attachments = Array.isArray(results[1].data) ? results[1].data : [] |
|
const routeFlowInstanceId = String(this.$route.query.flowInstanceId || '') |
|
if (routeFlowInstanceId && !this.report.flowInstanceId) this.$set(this.report, 'flowInstanceId', routeFlowInstanceId) |
|
if (this.$route.query.canApprove === '1' && this.report.canApprove !== true && String(this.report.canApprove) !== 'true') { |
|
this.$set(this.report, 'canApprove', true) |
|
} |
|
await this.resolveCurrentTask() |
|
this.loaded = true |
|
} catch (error) { |
|
this.loadError = '隐患详情或附件加载失败,请稍后重试。' |
|
} finally { |
|
this.loading = false |
|
} |
|
}, |
|
async resolveCurrentTask() { |
|
this.taskId = String(this.$route.query.taskId || '') |
|
const canApprove = this.report.canApprove === true || String(this.report.canApprove) === 'true' |
|
if (this.taskId || !canApprove || !this.report.flowInstanceId) return |
|
|
|
try { |
|
const response = await getHazardProcessDetail(this.report.flowInstanceId) |
|
const currentTask = this.findCurrentTask(response.data) |
|
this.taskId = currentTask ? String(currentTask.taskId || '') : '' |
|
} catch (error) { |
|
this.taskId = '' |
|
} |
|
}, |
|
findCurrentTask(data) { |
|
const tasks = this.normalizeTaskList(data) |
|
if (!tasks.length) return null |
|
return tasks.find(task => task.taskId && !task.endTime && !task.finishTime) || |
|
tasks.find(task => task.taskId) || |
|
null |
|
}, |
|
normalizeTaskList(data) { |
|
const tasks = [] |
|
const visit = value => { |
|
if (Array.isArray(value)) { |
|
value.forEach(visit) |
|
return |
|
} |
|
if (!value || typeof value !== 'object') return |
|
if (Object.prototype.hasOwnProperty.call(value, 'taskId')) tasks.push(value) |
|
Object.keys(value).forEach(key => { |
|
if (key !== 'taskId') visit(value[key]) |
|
}) |
|
} |
|
visit(data) |
|
return tasks |
|
}, |
|
handleAttachmentUpload(payload) { |
|
uploadHazardAttachment(payload.file, payload.attachmentType).then(response => { |
|
const data = response.data |
|
const items = Array.isArray(data) ? data : (data ? [data] : []) |
|
if (!items.length) throw new Error('上传接口未返回附件信息') |
|
payload.done(items.map(item => ({ |
|
...item, |
|
reportId: item.reportId || this.reportId, |
|
attachmentType: item.attachmentType || payload.attachmentType |
|
}))) |
|
this.$modal.msgSuccess('附件上传成功,审批时将保存关联') |
|
}).catch(() => { |
|
payload.fail() |
|
}) |
|
}, |
|
async handleAuditSubmit(payload) { |
|
if (!this.taskId) { |
|
this.$modal.msgWarning('当前未获取到任务 ID,无法执行审批;请从待办任务入口进入。') |
|
return |
|
} |
|
this.submitting = true |
|
try { |
|
await updateHazardReport(payload.saveData) |
|
await completeHazardAudit(payload.completeData) |
|
this.$modal.msgSuccess(payload.completeData.result === '1' ? '审核已通过' : '上报已驳回') |
|
this.goBack() |
|
} catch (error) { |
|
this.$modal.msgError('操作未完成:补录保存或流程审批失败') |
|
} finally { |
|
this.submitting = false |
|
} |
|
}, |
|
handleSwitchLevel(data) { |
|
this.$confirm('切换等级后旧流程将作废,并按新等级重新发起审批。是否继续?', '重新评估等级', { |
|
confirmButtonText: '确认切换', |
|
cancelButtonText: '取消', |
|
type: 'warning' |
|
}).then(async() => { |
|
this.submitting = true |
|
try { |
|
await switchHazardLevel({ |
|
reportId: this.reportId, |
|
newHazardLevel: data.newHazardLevel, |
|
switchReason: data.switchReason |
|
}) |
|
this.$modal.msgSuccess('隐患等级已切换,新流程已启动') |
|
this.goBack() |
|
} catch (error) { |
|
this.$modal.msgError('隐患等级切换失败') |
|
} finally { |
|
this.submitting = false |
|
} |
|
}).catch(() => {}) |
|
}, |
|
goBack() { |
|
if (window.history.length > 1) { |
|
this.$tab.closePage().then(() => {}) |
|
return |
|
} |
|
this.$router.push('/') |
|
} |
|
} |
|
} |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.hazard-audit-page { min-height: calc(100vh - 52px); padding: 16px 20px 40px; background: #f0f2f5; } |
|
.page-header { margin-bottom: 14px; padding: 14px 18px; border-radius: 8px; background: #fff; } |
|
.route-alert { margin-bottom: 14px; } |
|
.audit-content { display: grid; grid-template-columns: minmax(330px, 1.05fr) minmax(540px, 1.9fr) minmax(280px, .9fr); align-items: start; gap: 14px; min-height: 280px; } |
|
::v-deep .audit-card { margin: 0; border: 0; border-radius: 8px; } |
|
::v-deep .audit-card > .el-card__header { padding: 16px; border-bottom-color: #ebeef5; } |
|
::v-deep .audit-card > .el-card__body { padding: 16px; } |
|
@media (max-width: 1450px) { |
|
.audit-content { grid-template-columns: minmax(300px, 1fr) minmax(500px, 1.6fr); } |
|
.audit-content > :last-child { grid-column: 1 / -1; } |
|
} |
|
@media (max-width: 980px) { |
|
.audit-content { grid-template-columns: 1fr; } |
|
.audit-content > :last-child { grid-column: auto; } |
|
} |
|
</style>
|
|
|