|
@@ -0,0 +1,662 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="app-container">
|
|
|
|
|
+ <ContentWrap style="border: 0">
|
|
|
|
|
+ <el-form
|
|
|
|
|
+ class="-mb-15px"
|
|
|
|
|
+ :model="queryParams"
|
|
|
|
|
+ ref="queryForm"
|
|
|
|
|
+ :inline="true"
|
|
|
|
|
+ label-width="100px"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-row :gutter="20">
|
|
|
|
|
+ <el-col :span="24" :xs="24" :sm="12" :md="6">
|
|
|
|
|
+ <el-form-item label="事件级别" prop="accidentGrade">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="queryParams.accidentGrade"
|
|
|
|
|
+ placeholder="请输入事件级别"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ @keyup.enter="handleQuery"
|
|
|
|
|
+ style="width: 200px"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ <el-col :span="24" :xs="24" :sm="12" :md="6">
|
|
|
|
|
+ <el-form-item label="事件类型" prop="accidentType">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="queryParams.accidentType"
|
|
|
|
|
+ placeholder="请选择事件类型"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ style="width: 200px"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ <el-col :span="24" :xs="24" :sm="24" :md="12">
|
|
|
|
|
+ <el-form-item style="display: block">
|
|
|
|
|
+ <el-button type="primary" @click="handleQuery" :icon="Search">搜索</el-button>
|
|
|
|
|
+ <el-button @click="resetQuery" :icon="Refresh">重置</el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </ContentWrap>
|
|
|
|
|
+
|
|
|
|
|
+ <ContentWrap style="border: 0">
|
|
|
|
|
+ <el-table
|
|
|
|
|
+ v-loading="loading"
|
|
|
|
|
+ :data="list"
|
|
|
|
|
+ row-key="id"
|
|
|
|
|
+ border
|
|
|
|
|
+ style="width: 100%"
|
|
|
|
|
+ :header-cell-style="{ background: '#f5f7fa', color: '#333', height: '50px' }"
|
|
|
|
|
+ :cell-style="{ padding: '12px 8px' }"
|
|
|
|
|
+ height="70vh"
|
|
|
|
|
+ :max-height="tableHeight"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-table-column prop="actualTime" label="事件时间" align="center" min-width="120">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ {{ formatDate(row.actualTime) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="accidentGrade" label="事件级别" align="center" />
|
|
|
|
|
+ <el-table-column prop="accidentType" label="事件类型" align="center" />
|
|
|
|
|
+ <el-table-column prop="accidentType" label="事件状态" align="center" width="100">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <dict-tag :type="DICT_TYPE.ACCIDENT_REPORT_STATUS" :value="scope.row.status" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="lossSituation"
|
|
|
|
|
+ label="事件损失情况"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
|
+ min-width="150"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="accidentAddress"
|
|
|
|
|
+ label="事件地址"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ min-width="150"
|
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column prop="deptName" label="部门名称" align="center" />
|
|
|
|
|
+ <el-table-column prop="dutyPerson" label="现场负责人" align="center" width="100" />
|
|
|
|
|
+
|
|
|
|
|
+ <el-table-column label="操作" align="center" width="180" fixed="right">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-button link type="primary" @click="openApprovalDialog(row)" :icon="View">
|
|
|
|
|
+ 流转信息
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ link
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ @click="openDialog(row.id)"
|
|
|
|
|
+ :icon="Edit"
|
|
|
|
|
+ v-hasPermi="['rq:iot-accident-report:approval']"
|
|
|
|
|
+ v-if="row.currentPerson.includes(currentUserId) && row.status !== 'finished'"
|
|
|
|
|
+ >
|
|
|
|
|
+ 审批
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 分页 -->
|
|
|
|
|
+ <div class="mt-2 mb-2 float-right">
|
|
|
|
|
+ <el-pagination
|
|
|
|
|
+ v-model:current-page="queryParams.pageNo"
|
|
|
|
|
+ v-model:page-size="queryParams.pageSize"
|
|
|
|
|
+ :total="total"
|
|
|
|
|
+ layout="total, sizes, prev, pager, next"
|
|
|
|
|
+ @size-change="handleSizeChange"
|
|
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
|
|
+ background
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </ContentWrap>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 审批流程弹窗 -->
|
|
|
|
|
+ <!-- 审批流程弹窗 -->
|
|
|
|
|
+ <!-- 审批流程抽屉 -->
|
|
|
|
|
+ <el-drawer
|
|
|
|
|
+ :title="approvalDialogTitle"
|
|
|
|
|
+ v-model="approvalDialogVisible"
|
|
|
|
|
+ direction="rtl"
|
|
|
|
|
+ size="600px"
|
|
|
|
|
+ :with-header="true"
|
|
|
|
|
+ :close-on-click-modal="false"
|
|
|
|
|
+ destroy-on-close
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div
|
|
|
|
|
+ style="
|
|
|
|
|
+ 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;
|
|
|
|
|
+ "
|
|
|
|
|
+ >
|
|
|
|
|
+ <span>{{ approvalDialogTitle }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 时间线展示审批记录 -->
|
|
|
|
|
+ <el-timeline>
|
|
|
|
|
+ <el-timeline-item
|
|
|
|
|
+ v-for="(item, index) in approvalProcessList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ :timestamp="formatDate(item.createTime)"
|
|
|
|
|
+ placement="top"
|
|
|
|
|
+ :color="getStatusColor(item.status)"
|
|
|
|
|
+ :icon="Check"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-card shadow="never" class="text-sm">
|
|
|
|
|
+ <p>节点名称: {{ item.nodeName }}</p>
|
|
|
|
|
+ <p>操作人: {{ item.operator }}</p>
|
|
|
|
|
+ <p class="pt-1">审批状态:{{ item.status }}</p>
|
|
|
|
|
+ <p class="pt-1">描述:{{ item.description }}</p>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-timeline-item>
|
|
|
|
|
+ </el-timeline>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 审批建议输入框 -->
|
|
|
|
|
+ <!-- <el-form-item label="审批建议" prop="suggestion">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="approvalSuggestion"
|
|
|
|
|
+ type="textarea"
|
|
|
|
|
+ :rows="3"
|
|
|
|
|
+ placeholder="请输入审批建议"
|
|
|
|
|
+ maxlength="500"
|
|
|
|
|
+ show-word-limit
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item> -->
|
|
|
|
|
+
|
|
|
|
|
+ <!-- <template #footer>
|
|
|
|
|
+ <div class="dialog-footer">
|
|
|
|
|
+ <el-button @click="handleApprovalCancel">取 消</el-button>
|
|
|
|
|
+
|
|
|
|
|
+ <el-button type="primary" @click="handleApprovalSubmit">上 报</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template> -->
|
|
|
|
|
+ </el-drawer>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 审批建议弹窗 -->
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ title="审批"
|
|
|
|
|
+ v-model="dialog"
|
|
|
|
|
+ width="500px"
|
|
|
|
|
+ append-to-body
|
|
|
|
|
+ :close-on-click-modal="false"
|
|
|
|
|
+ destroy-on-close
|
|
|
|
|
+ custom-class="self-dialog"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #title>
|
|
|
|
|
+ <div
|
|
|
|
|
+ style="
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
|
|
+ padding-bottom: 20px;
|
|
|
|
|
+ padding-left: 20px;
|
|
|
|
|
+ width: 114%;
|
|
|
|
|
+ margin-left: -15px;
|
|
|
|
|
+ "
|
|
|
|
|
+ >
|
|
|
|
|
+ <span>审批</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <el-form :model="approvalForm">
|
|
|
|
|
+ <el-form-item label="审批建议" prop="suggestion">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="approvalForm.suggestion"
|
|
|
|
|
+ type="textarea"
|
|
|
|
|
+ :rows="4"
|
|
|
|
|
+ placeholder="请输入审批建议"
|
|
|
|
|
+ maxlength="500"
|
|
|
|
|
+ show-word-limit
|
|
|
|
|
+ style="width: 100%"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <div class="dialog-footer">
|
|
|
|
|
+ <el-button @click="handleApprovalCancel">取 消</el-button>
|
|
|
|
|
+ <el-button type="primary" @click="handleApprovalSubmit">上报</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </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, Check } from '@element-plus/icons-vue'
|
|
|
|
|
+import { defaultProps } from '@/utils/tree'
|
|
|
|
|
+import { handleTree } from '@/utils/tree'
|
|
|
|
|
+import * as DeptApi from '@/api/system/dept'
|
|
|
|
|
+import { IotApprovalApi } 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 { useUserStore } from '@/store/modules/user'
|
|
|
|
|
+
|
|
|
|
|
+// Data
|
|
|
|
|
+const loading = ref(false)
|
|
|
|
|
+const submitLoading = ref(false)
|
|
|
|
|
+const list = ref([])
|
|
|
|
|
+const total = ref(0)
|
|
|
|
|
+const open = ref(false)
|
|
|
|
|
+const title = ref('')
|
|
|
|
|
+const formRef = ref()
|
|
|
|
|
+const mode = ref('') // 'create' or 'update'
|
|
|
|
|
+const deptList2 = ref([]) // 树形结构
|
|
|
|
|
+let currentUserId = ref('')
|
|
|
|
|
+
|
|
|
|
|
+// 审批流程弹窗相关数据
|
|
|
|
|
+const approvalDialogVisible = ref(false)
|
|
|
|
|
+const approvalDialogTitle = ref('审批流程')
|
|
|
|
|
+const approvalProcessList = ref([]) // 存储审批流程信息
|
|
|
|
|
+// 审批建议输入框绑定的数据
|
|
|
|
|
+const approvalSuggestion = ref('')
|
|
|
|
|
+const approvalForm = reactive({
|
|
|
|
|
+ suggestion: ''
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+let dialog = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+// 根据审批状态返回对应的颜色
|
|
|
|
|
+// 根据审批状态返回对应的颜色
|
|
|
|
|
+const getStatusColor = (status) => {
|
|
|
|
|
+ switch (status) {
|
|
|
|
|
+ case '上报':
|
|
|
|
|
+ return '#67C23A' // 绿色
|
|
|
|
|
+ case '上报中':
|
|
|
|
|
+ return '#E6A23C' // 黄色
|
|
|
|
|
+ case '未开始':
|
|
|
|
|
+ return '#909399' // 灰色
|
|
|
|
|
+ case '提交上报':
|
|
|
|
|
+ return '#409EFF' // 蓝色(默认)
|
|
|
|
|
+ default:
|
|
|
|
|
+ return '#409EFF' // 默认蓝色
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 打开审批流程弹窗并加载数据
|
|
|
|
|
+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: '发起人'
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error('获取审批流程失败')
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+let currentRow = ref('')
|
|
|
|
|
+const openDialog = (id) => {
|
|
|
|
|
+ currentRow.value = id
|
|
|
|
|
+ dialog.value = true
|
|
|
|
|
+ approvalForm.suggestion = '' // 清空审批建议
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 处理审批上报
|
|
|
|
|
+const handleApprovalSubmit = async () => {
|
|
|
|
|
+ if (!approvalForm.suggestion.trim()) {
|
|
|
|
|
+ ElMessage.warning('请填写审批建议')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 调用上报审批的 API,携带审批建议
|
|
|
|
|
+ await IotApprovalApi.createApproval({
|
|
|
|
|
+ id: currentRow.value,
|
|
|
|
|
+ suggestion: approvalForm.suggestion
|
|
|
|
|
+ })
|
|
|
|
|
+ ElMessage.success('上报成功')
|
|
|
|
|
+ dialog.value = false
|
|
|
|
|
+ getList() // 刷新列表
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error('上报失败')
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 取消审批操作
|
|
|
|
|
+const handleApprovalCancel = () => {
|
|
|
|
|
+ dialog.value = false
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 表单数据
|
|
|
|
|
+const formData = ref({
|
|
|
|
|
+ actualTime: null, // 使用时间戳格式
|
|
|
|
|
+ accidentGrade: '',
|
|
|
|
|
+ accidentType: '',
|
|
|
|
|
+ accidentAddress: '',
|
|
|
|
|
+
|
|
|
|
|
+ dutyPerson: '',
|
|
|
|
|
+ lossSituation: '',
|
|
|
|
|
+ emergencyMeasure: '',
|
|
|
|
|
+ description: '',
|
|
|
|
|
+ pic: '',
|
|
|
|
|
+ remark: ''
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 查询参数
|
|
|
|
|
+const queryParams = ref({
|
|
|
|
|
+ pageNo: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ actualTime: [],
|
|
|
|
|
+ accidentGrade: undefined,
|
|
|
|
|
+ accidentType: undefined
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 表单验证规则
|
|
|
|
|
+const formRules = reactive({
|
|
|
|
|
+ actualTime: [{ required: true, message: '请选择事件时间', trigger: 'change' }],
|
|
|
|
|
+ accidentGrade: [{ required: true, message: '请输入事件级别', trigger: 'blur' }],
|
|
|
|
|
+ accidentType: [{ required: true, message: '请选择事件类型', trigger: 'change' }],
|
|
|
|
|
+ accidentAddress: [{ required: true, message: '请输入事件地址', trigger: 'blur' }],
|
|
|
|
|
+ deptId: [{ required: true, message: '请选择所属部门', trigger: 'change' }],
|
|
|
|
|
+ deptName: [{ required: true, message: '请输入队伍名称', trigger: 'blur' }],
|
|
|
|
|
+ dutyPerson: [{ required: true, message: '请输入现场负责人', trigger: 'blur' }]
|
|
|
|
|
+ // description: [
|
|
|
|
|
+ // { required: true, message: '请输入事件简要经过', trigger: 'blur' },
|
|
|
|
|
+ // { min: 1, max: 1000, message: '事件简要经过长度应在1-1000之间', trigger: 'blur' }
|
|
|
|
|
+ // ]
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 计算属性
|
|
|
|
|
+const isMobile = computed(() => {
|
|
|
|
|
+ return window.innerWidth < 768
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const tableHeight = computed(() => {
|
|
|
|
|
+ if (isMobile.value) {
|
|
|
|
|
+ return window.innerHeight - 300 // 为移动端减少高度,考虑其他元素占用空间
|
|
|
|
|
+ }
|
|
|
|
|
+ return '70vh'
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// Methods
|
|
|
|
|
+const getList = async () => {
|
|
|
|
|
+ loading.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await IotApprovalApi.getApprovalList(queryParams.value)
|
|
|
|
|
+ list.value = response.list
|
|
|
|
|
+ total.value = response.total
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ ElMessage.error('获取列表失败')
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleSizeChange = (val) => {
|
|
|
|
|
+ queryParams.value.pageSize = val
|
|
|
|
|
+ queryParams.value.pageNo = 1 // 重置为第一页
|
|
|
|
|
+ getList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleCurrentChange = (val) => {
|
|
|
|
|
+ queryParams.value.pageNo = val
|
|
|
|
|
+ getList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const resetQuery = () => {
|
|
|
|
|
+ // 重置查询参数
|
|
|
|
|
+ queryParams.value = {
|
|
|
|
|
+ pageNo: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ actualTime: [],
|
|
|
|
|
+ accidentGrade: undefined,
|
|
|
|
|
+ accidentType: undefined
|
|
|
|
|
+ }
|
|
|
|
|
+ handleQuery()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleQuery = () => {
|
|
|
|
|
+ queryParams.value.pageNo = 1
|
|
|
|
|
+ getList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const reset = () => {
|
|
|
|
|
+ formData.value = {
|
|
|
|
|
+ id: undefined,
|
|
|
|
|
+ actualTime: null,
|
|
|
|
|
+ accidentGrade: '',
|
|
|
|
|
+ accidentType: '',
|
|
|
|
|
+ accidentAddress: '',
|
|
|
|
|
+ // deptId: null,
|
|
|
|
|
+ // deptName: '',
|
|
|
|
|
+ dutyPerson: '',
|
|
|
|
|
+ lossSituation: '',
|
|
|
|
|
+ emergencyMeasure: '',
|
|
|
|
|
+ description: '',
|
|
|
|
|
+ pic: '',
|
|
|
|
|
+ remark: ''
|
|
|
|
|
+ }
|
|
|
|
|
+ if (formRef.value) {
|
|
|
|
|
+ formRef.value.resetFields()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const submitForm = async () => {
|
|
|
|
|
+ if (!formRef.value) return
|
|
|
|
|
+
|
|
|
|
|
+ await formRef.value.validate(async (valid) => {
|
|
|
|
|
+ if (valid) {
|
|
|
|
|
+ submitLoading.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 在提交前确保时间是时间戳格式
|
|
|
|
|
+ const submitData = { ...formData.value }
|
|
|
|
|
+
|
|
|
|
|
+ if (mode.value === 'update' && formData.value.id) {
|
|
|
|
|
+ // 更新API调用
|
|
|
|
|
+ submitData.id = formData.value.id
|
|
|
|
|
+ await IotApprovalApi.updateFailure(submitData)
|
|
|
|
|
+ ElMessage.success('更新成功')
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 创建API调用
|
|
|
|
|
+ await IotApprovalApi.createFailure(submitData)
|
|
|
|
|
+ ElMessage.success('新增成功')
|
|
|
|
|
+ }
|
|
|
|
|
+ open.value = false
|
|
|
|
|
+ getList()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error(error.message || '操作失败')
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ submitLoading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error('请填写必填项')
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const downloadFile = (response) => {
|
|
|
|
|
+ // 创建 blob 对象
|
|
|
|
|
+ const blob = new Blob([response], {
|
|
|
|
|
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 获取文件名
|
|
|
|
|
+ let fileName = '事故事件上报.xlsx'
|
|
|
|
|
+ const disposition = response.headers ? response.headers['content-disposition'] : ''
|
|
|
|
|
+ if (disposition) {
|
|
|
|
|
+ const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
|
|
|
|
|
+ const matches = filenameRegex.exec(disposition)
|
|
|
|
|
+ if (matches != null && matches[1]) {
|
|
|
|
|
+ fileName = matches[1].replace(/['"]/g, '')
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 创建下载链接
|
|
|
|
|
+ const url = window.URL.createObjectURL(blob)
|
|
|
|
|
+ const link = document.createElement('a')
|
|
|
|
|
+ link.href = url
|
|
|
|
|
+ link.setAttribute('download', fileName)
|
|
|
|
|
+
|
|
|
|
|
+ // 触发下载
|
|
|
|
|
+ document.body.appendChild(link)
|
|
|
|
|
+ link.click()
|
|
|
|
|
+
|
|
|
|
|
+ // 清理
|
|
|
|
|
+ document.body.removeChild(link)
|
|
|
|
|
+ window.URL.revokeObjectURL(url)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+let exportLoading = ref(false)
|
|
|
|
|
+const handleExport = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ exportLoading.value = true
|
|
|
|
|
+ // 调用导出接口
|
|
|
|
|
+ const response = await IotApprovalApi.exportFailure(queryParams.value)
|
|
|
|
|
+
|
|
|
|
|
+ // 下载文件
|
|
|
|
|
+ downloadFile(response)
|
|
|
|
|
+ exportLoading.value = false
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error('导出失败,请重试')
|
|
|
|
|
+ console.error('导出错误:', error)
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ exportLoading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const cancel = () => {
|
|
|
|
|
+ open.value = false
|
|
|
|
|
+ reset()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 监听窗口大小变化
|
|
|
|
|
+const handleResize = () => {
|
|
|
|
|
+ // 这里可以添加响应式逻辑
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Lifecycle hooks
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ window.addEventListener('resize', handleResize)
|
|
|
|
|
+ getList()
|
|
|
|
|
+ deptList2.value = handleTree(await DeptApi.getSimpleDeptList())
|
|
|
|
|
+
|
|
|
|
|
+ currentUserId.value = useUserStore().user.id
|
|
|
|
|
+
|
|
|
|
|
+ console.log(',,,,,,,,,,,,,,,,,,,,', useUserStore().user)
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ window.removeEventListener('resize', handleResize)
|
|
|
|
|
+})
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+.app-container {
|
|
|
|
|
+ padding: 15px 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 移动端适配 */
|
|
|
|
|
+@media (max-width: 768px) {
|
|
|
|
|
+ .app-container {
|
|
|
|
|
+ padding: 10px 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .el-form-item__label {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ text-align: left;
|
|
|
|
|
+ padding-bottom: 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .el-form-item__content {
|
|
|
|
|
+ margin-left: 0 !important;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .el-button + .el-button {
|
|
|
|
|
+ margin-left: 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* 调整表格字体大小 */
|
|
|
|
|
+ :deep(.el-table .el-table__cell) {
|
|
|
|
|
+ padding: 8px 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ :deep(.el-table th.el-table__cell) {
|
|
|
|
|
+ padding: 10px 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 通用样式 */
|
|
|
|
|
+.dialog-footer {
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+:deep(.el-textarea__inner) {
|
|
|
|
|
+ min-height: 80px !important;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 移动端分页样式 */
|
|
|
|
|
+.mt-2.flex.justify-right {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ margin-top: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 移动端按钮样式 */
|
|
|
|
|
+@media (max-width: 768px) {
|
|
|
|
|
+ .el-button {
|
|
|
|
|
+ margin-bottom: 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::v-deep .el-button {
|
|
|
|
|
+ border-radius: 3px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 抽屉样式优化 */
|
|
|
|
|
+::v-deep .el-drawer__body {
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 时间线样式优化 */
|
|
|
|
|
+::deep(.el-timeline-item__content) {
|
|
|
|
|
+ padding: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::deep(.el-card__body) {
|
|
|
|
|
+ padding: 15px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 输入框样式优化 */
|
|
|
|
|
+::deep(.el-textarea__inner) {
|
|
|
|
|
+ min-height: 100px !important;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 移动端适配 */
|
|
|
|
|
+@media (max-width: 768px) {
|
|
|
|
|
+ .el-drawer {
|
|
|
|
|
+ width: 90% !important;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|