|
|
@@ -63,7 +63,7 @@
|
|
|
height="70vh"
|
|
|
:max-height="tableHeight"
|
|
|
>
|
|
|
- <el-table-column prop="actualTime" label="事件时间" align="center" min-width="120">
|
|
|
+ <el-table-column prop="actualTime" label="事件时间" align="center" min-width="150">
|
|
|
<template #default="{ row }">
|
|
|
{{ formatDate(row.actualTime) }}
|
|
|
</template>
|
|
|
@@ -92,8 +92,13 @@
|
|
|
/>
|
|
|
<el-table-column prop="deptName" label="部门名称" align="center" />
|
|
|
<el-table-column prop="dutyPerson" label="现场负责人" align="center" width="100" />
|
|
|
+ <el-table-column prop="actualTime" label="创建时间" align="center" min-width="150">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ formatDate(row.createTime) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
|
|
|
- <el-table-column label="操作" align="center" width="200" fixed="right">
|
|
|
+ <el-table-column label="操作" align="center" width="150" fixed="right">
|
|
|
<template #default="{ row }">
|
|
|
<!-- <el-button
|
|
|
link
|
|
|
@@ -111,22 +116,23 @@
|
|
|
v-hasPermi="['rq:iot-accident-report:query']"
|
|
|
>详情</el-button
|
|
|
>
|
|
|
- <el-button
|
|
|
+ <el-button link type="primary" @click="openApprovalDialog(row)"> 流转信息 </el-button>
|
|
|
+ <!-- <el-button
|
|
|
link
|
|
|
type="primary"
|
|
|
@click="openForm('update', row)"
|
|
|
:icon="Edit"
|
|
|
v-hasPermi="['rq:iot-accident-report:update']"
|
|
|
>编辑</el-button
|
|
|
- >
|
|
|
- <el-button
|
|
|
+ > -->
|
|
|
+ <!-- <el-button
|
|
|
link
|
|
|
type="danger"
|
|
|
@click="handleDelete(row)"
|
|
|
:icon="Delete"
|
|
|
v-hasPermi="['rq:iot-accident-report:delete']"
|
|
|
>删除</el-button
|
|
|
- >
|
|
|
+ > -->
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
@@ -326,13 +332,95 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
+
|
|
|
+ <el-drawer
|
|
|
+ :title="approvalDialogTitle"
|
|
|
+ v-model="approvalDialogVisible"
|
|
|
+ direction="rtl"
|
|
|
+ size="650px"
|
|
|
+ :with-header="true"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <template #header>
|
|
|
+ <div class="drawer-header">
|
|
|
+ <span>{{ approvalDialogTitle }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <!-- 专业化的审批流程时间线 -->
|
|
|
+ <div class="approval-process-container">
|
|
|
+ <el-timeline v-if="approvalProcessList.length > 0">
|
|
|
+ <el-timeline-item
|
|
|
+ v-for="(item, index) in approvalProcessList"
|
|
|
+ :key="index"
|
|
|
+ placement="top"
|
|
|
+ :color="getNodeStatusColor(item.status)"
|
|
|
+ :icon="Check"
|
|
|
+ >
|
|
|
+ <el-card
|
|
|
+ shadow="never"
|
|
|
+ class="approval-card"
|
|
|
+ :class="{ 'status-completed': item.status === '已完成' || item.status === '已批准' }"
|
|
|
+ >
|
|
|
+ <div class="card-header">
|
|
|
+ <div class="node-info">
|
|
|
+ <el-tag :type="getTagTypeByStatus(item.status)" size="small" class="status-tag">
|
|
|
+ {{ item.status }}
|
|
|
+ </el-tag>
|
|
|
+ <span class="node-name">{{ item.nodeName }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="operator-time">
|
|
|
+ <span class="time">{{ formatDate(item.createTime) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="card-content">
|
|
|
+ <div class="opinion-section">
|
|
|
+ <span class="label">操作人:</span>
|
|
|
+ <span class="opinion">{{ item.operator }}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="description-section mt-1" v-if="item.description">
|
|
|
+ <span class="label">审批意见:</span>
|
|
|
+ <span class="description">{{ item.description }}</span>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="attachment-section"
|
|
|
+ v-if="item.attachments && item.attachments.length > 0"
|
|
|
+ >
|
|
|
+ <span class="label">附件:</span>
|
|
|
+ <div class="attachments">
|
|
|
+ <el-link
|
|
|
+ v-for="(attachment, idx) in item.attachments"
|
|
|
+ :key="idx"
|
|
|
+ type="primary"
|
|
|
+ :href="attachment.url"
|
|
|
+ target="_blank"
|
|
|
+ class="attachment-link"
|
|
|
+ >
|
|
|
+ {{ attachment.name }}
|
|
|
+ </el-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </el-timeline-item>
|
|
|
+ </el-timeline>
|
|
|
+
|
|
|
+ <!-- 无数据提示 -->
|
|
|
+ <div v-else class="no-data">
|
|
|
+ <el-empty description="暂无审批流程信息" :image-size="100" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-drawer>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import { ref, reactive, onMounted, computed } from 'vue'
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
-import { Search, Refresh, Plus, Edit, Delete, TopRight, View } from '@element-plus/icons-vue'
|
|
|
+import { Search, Refresh, Plus, Edit, Delete, TopRight, View, Check } from '@element-plus/icons-vue'
|
|
|
import { defaultProps } from '@/utils/tree'
|
|
|
import { handleTree } from '@/utils/tree'
|
|
|
import * as DeptApi from '@/api/system/dept'
|
|
|
@@ -340,6 +428,7 @@ import { IotFailureApi } from '@/api/pms/qhse/index'
|
|
|
import UploadImage from '@/components/UploadFile/src/UploadImg.vue'
|
|
|
import { formatDate } from '@/utils/formatTime'
|
|
|
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
|
|
|
+import { IotApprovalApi } from '@/api/pms/qhse/index'
|
|
|
|
|
|
// Data
|
|
|
const loading = ref(false)
|
|
|
@@ -617,6 +706,79 @@ const cancel = () => {
|
|
|
reset()
|
|
|
}
|
|
|
|
|
|
+const approvalDialogVisible = ref(false)
|
|
|
+const approvalDialogTitle = ref('审批流程')
|
|
|
+const approvalProcessList = ref([]) // 存储审批流程信息
|
|
|
+const approvalSuggestion = ref('')
|
|
|
+// 根据状态返回标签类型
|
|
|
+const getTagTypeByStatus = (status) => {
|
|
|
+ const tagTypeMap = {
|
|
|
+ 待处理: 'warning',
|
|
|
+ 处理中: 'info',
|
|
|
+ 已完成: 'success',
|
|
|
+ 已驳回: 'danger',
|
|
|
+ 已撤销: 'info',
|
|
|
+ 已批准: 'success',
|
|
|
+ 审批中: 'primary',
|
|
|
+ 上报: 'success',
|
|
|
+ 提交上报: 'primary'
|
|
|
+ }
|
|
|
+ return tagTypeMap[status] || 'info'
|
|
|
+}
|
|
|
+const getNodeStatusColor = (status) => {
|
|
|
+ const colorMap = {
|
|
|
+ 待处理: '#E6A23C',
|
|
|
+ 处理中: '#409EFF',
|
|
|
+ 已完成: '#67C23A',
|
|
|
+ 已驳回: '#F56C6C',
|
|
|
+ 已撤销: '#909399',
|
|
|
+ 已批准: '#67C23A',
|
|
|
+ 审批中: '#409EFF',
|
|
|
+ 上报: '#229242',
|
|
|
+ 提交上报: '#409EFF'
|
|
|
+ }
|
|
|
+ return colorMap[status] || '#90939'
|
|
|
+}
|
|
|
+
|
|
|
+const openApprovalDialog = async (row) => {
|
|
|
+ approvalDialogVisible.value = true
|
|
|
+ approvalDialogTitle.value = `审批流程详情`
|
|
|
+ approvalSuggestion.value = '' // 清空审批建议
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await IotApprovalApi.getApprovalProcess(row.id)
|
|
|
+ const processList = response.list || []
|
|
|
+
|
|
|
+ // 按 createTime 升序排序(时间正序)
|
|
|
+ approvalProcessList.value = processList.sort((a, b) => a.createTime - b.createTime)
|
|
|
+
|
|
|
+ // 如果没有数据,添加一条默认的“发起人”记录
|
|
|
+ if (approvalProcessList.value.length === 0) {
|
|
|
+ approvalProcessList.value.push({
|
|
|
+ createTime: Date.now(),
|
|
|
+ operator: '系统管理员',
|
|
|
+ status: '提交上报',
|
|
|
+ description: '发起事故事件上报申请',
|
|
|
+ nodeName: '上报发起',
|
|
|
+ opinion: ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('获取审批流程失败')
|
|
|
+ // 即使出错也显示一个基本记录
|
|
|
+ approvalProcessList.value = [
|
|
|
+ {
|
|
|
+ createTime: Date.now(),
|
|
|
+ operator: '系统',
|
|
|
+ status: '错误',
|
|
|
+ description: '无法获取审批流程信息',
|
|
|
+ nodeName: '系统通知',
|
|
|
+ opinion: ''
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 监听窗口大小变化
|
|
|
const handleResize = () => {
|
|
|
// 这里可以添加响应式逻辑
|
|
|
@@ -695,4 +857,139 @@ onUnmounted(() => {
|
|
|
::v-deep .el-button {
|
|
|
border-radius: 3px;
|
|
|
}
|
|
|
+
|
|
|
+.drawer-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+ padding-bottom: 20px;
|
|
|
+ padding-left: 20px;
|
|
|
+ width: 108%;
|
|
|
+ margin-left: -15px;
|
|
|
+}
|
|
|
+
|
|
|
+.approval-process-container {
|
|
|
+ padding: 10px 15px;
|
|
|
+
|
|
|
+ .no-data {
|
|
|
+ text-align: center;
|
|
|
+ padding: 40px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .approval-card {
|
|
|
+ border: 1px solid #ebeef5;
|
|
|
+ border-radius: 6px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
|
+ transition: all 0.3s ease;
|
|
|
+
|
|
|
+ &.status-completed {
|
|
|
+ border-left: 4px solid #67c23a;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding-bottom: 12px;
|
|
|
+ border-bottom: 1px dashed #ebeef5;
|
|
|
+
|
|
|
+ .node-info {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+
|
|
|
+ .status-tag {
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .node-name {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .operator-time {
|
|
|
+ .time {
|
|
|
+ color: #909399;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-content {
|
|
|
+ padding: 12px 0;
|
|
|
+
|
|
|
+ .label {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #606266;
|
|
|
+ display: inline-block;
|
|
|
+ width: 70px;
|
|
|
+ vertical-align: top;
|
|
|
+ }
|
|
|
+
|
|
|
+ .opinion,
|
|
|
+ .description {
|
|
|
+ color: #303133;
|
|
|
+ line-height: 1.6;
|
|
|
+ }
|
|
|
+
|
|
|
+ .attachment-section {
|
|
|
+ margin-top: 8px;
|
|
|
+
|
|
|
+ .attachments {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 5px;
|
|
|
+ margin-top: 5px;
|
|
|
+
|
|
|
+ .attachment-link {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ padding-left: 70px;
|
|
|
+ text-decoration: none;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ text-decoration: underline;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .approval-process-container {
|
|
|
+ padding: 5px;
|
|
|
+
|
|
|
+ .approval-card {
|
|
|
+ .card-header {
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ align-items: flex-start;
|
|
|
+
|
|
|
+ .node-info {
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-content {
|
|
|
+ .label {
|
|
|
+ width: auto;
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .attachment-section .attachment-link {
|
|
|
+ padding-left: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|