0922
This commit is contained in:
		
							
								
								
									
										49
									
								
								src/api/zhinengxunjian/baoxiou/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/api/zhinengxunjian/baoxiou/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| import request from '@/utils/request'; | ||||
| import { AxiosPromise } from 'axios'; | ||||
| //查询列表 | ||||
| export const baoxiulist = (query) => { | ||||
|   return request({ | ||||
|     url: '/ops/report/list', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
| //新增待办事项 | ||||
| export const addbaoxiu = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/report', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //修改待办事项 | ||||
| export const updatebaoxiu = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/report', | ||||
|     method: 'put', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //删除待办事项 | ||||
|  | ||||
| export function delbaoxiu(ids) { | ||||
|   return request({ | ||||
|     url: `/ops/report/${ids}`, // 拼接ids作为路径参数 | ||||
|     method: 'delete' | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export const baoxiuDetail = (id) => { | ||||
|   return request({ | ||||
|     url: `/ops/report/${id}`, | ||||
|     method: 'get' | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export const uploadbaoxiu = (data) => { | ||||
|   return request({ | ||||
|     url: '/resource/oss/upload', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
							
								
								
									
										49
									
								
								src/api/zhinengxunjian/shiyan/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/api/zhinengxunjian/shiyan/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| import request from '@/utils/request'; | ||||
| import { AxiosPromise } from 'axios'; | ||||
| //查询列表 | ||||
| export const shiyanlist = (query) => { | ||||
|   return request({ | ||||
|     url: '/ops/testPlan/list', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
| //新增 | ||||
| export const addshiyan = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/testPlan', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //修改 | ||||
| export const updateshiyan = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/testPlan', | ||||
|     method: 'put', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //删除 | ||||
| export const delshiyan = (ids) => { | ||||
|   return request({ | ||||
|     url: `/ops/testPlan${ids}`, | ||||
|     method: 'delete' | ||||
|   }); | ||||
| }; | ||||
| //查询人员 | ||||
| export const shiyanUserlist = (query) => { | ||||
|   return request({ | ||||
|     url: '/ops/constructionUser/list', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| //详情 | ||||
| export const shiyanDetail = (id) => { | ||||
|   return request({ | ||||
|     url: `/ops/testPlan/${id}`, | ||||
|     method: 'get' | ||||
|   }); | ||||
| }; | ||||
							
								
								
									
										41
									
								
								src/api/zhinengxunjian/shiyan/renwu.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/api/zhinengxunjian/shiyan/renwu.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| import request from '@/utils/request'; | ||||
| import { AxiosPromise } from 'axios'; | ||||
| //查询列表 | ||||
| export const syrenwulist = (query) => { | ||||
|   return request({ | ||||
|     url: '/ops/testTask/list', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
| //新增 | ||||
| export const addsyrenwu = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/testTask', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //修改 | ||||
| export const updatesyrenwu = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/testTask', | ||||
|     method: 'put', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //删除 | ||||
| export const delsyrenwu = (ids) => { | ||||
|   return request({ | ||||
|     url: `/ops/testTask${ids}`, | ||||
|     method: 'delete' | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| //详情 | ||||
| export const syrenwuDetail = (id) => { | ||||
|   return request({ | ||||
|     url: `/ops/testTask/${id}`, | ||||
|     method: 'get' | ||||
|   }); | ||||
| }; | ||||
| @ -47,3 +47,10 @@ export const xunjianItemlist = (query) => { | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
| //详情 | ||||
| export const xunjianDetail = (id) => { | ||||
|   return request({ | ||||
|     url: `/ops/plan/${id}`, | ||||
|     method: 'get' | ||||
|   }); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										10
									
								
								src/api/zhinengxunjian/xunjian/jilu.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/api/zhinengxunjian/xunjian/jilu.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| import request from '@/utils/request'; | ||||
| import { AxiosPromise } from 'axios'; | ||||
| //查询列表 | ||||
| export const xunjianjilu = (query) => { | ||||
|   return request({ | ||||
|     url: '/ops/task/record', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
							
								
								
									
										46
									
								
								src/api/zhinengxunjian/xunjian/renwu.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/api/zhinengxunjian/xunjian/renwu.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| import request from '@/utils/request'; | ||||
| export const xjrenwulist = (query) => { | ||||
|   return request({ | ||||
|     url: '/ops/task/list', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
| //新增 | ||||
| export const addxjrenwu = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/task', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //修改 | ||||
| export const updatexjrenwu = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/task', | ||||
|     method: 'put', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
| //删除 | ||||
| export const delxjrenwu = (ids) => { | ||||
|   return request({ | ||||
|     url: `/ops/task/${ids}`, | ||||
|     method: 'delete' | ||||
|   }); | ||||
| }; | ||||
| //详情 | ||||
| export const xjrenwuDetail = (id) => { | ||||
|   return request({ | ||||
|     url: `/ops/task/${id}`, | ||||
|     method: 'get' | ||||
|   }); | ||||
| }; | ||||
| //导出 | ||||
| export const xjrenwuExport = (data) => { | ||||
|   return request({ | ||||
|     url: '/ops/task/export', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -129,12 +129,12 @@ | ||||
|       <el-dialog | ||||
|         v-model="createTaskDialogVisible" | ||||
|         title="新建报修任务" | ||||
|         width="800px" | ||||
|         width="900px" | ||||
|         :before-close="handleCancelCreateTask" | ||||
|         custom-class="beautiful-dialog" | ||||
|         center | ||||
|       > | ||||
|         <el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="100px" class="elegant-form"> | ||||
|         <el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="120px" class="elegant-form"> | ||||
|           <el-form-item label="报修名称*" prop="repairName"> | ||||
|             <el-input v-model="createTaskForm.repairName" placeholder="简要描述报修内容" /> | ||||
|           </el-form-item> | ||||
| @ -143,10 +143,8 @@ | ||||
|             <el-col :span="12"> | ||||
|               <el-form-item label="报修类型*" prop="repairType"> | ||||
|                 <el-select v-model="createTaskForm.repairType" placeholder="请选择类型"> | ||||
|                   <el-option label="设备故障" value="device" /> | ||||
|                   <el-option label="硬件故障" value="device" /> | ||||
|                   <el-option label="软件故障" value="software" /> | ||||
|                   <el-option label="网络故障" value="network" /> | ||||
|                   <el-option label="环境问题" value="environment" /> | ||||
|                 </el-select> | ||||
|               </el-form-item> | ||||
|             </el-col> | ||||
| @ -161,6 +159,12 @@ | ||||
|             </el-col> | ||||
|           </el-row> | ||||
|  | ||||
|           <el-form-item label="指派维修人*" prop="sendPerson"> | ||||
|             <el-select v-model="createTaskForm.sendPerson" placeholder="请选择维修人" :loading="loadingUsers"> | ||||
|               <el-option v-for="user in usersList" :key="user.id" :label="user.name" :value="user.id" /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="详细描述*" prop="detailedDescription"> | ||||
|             <el-input v-model="createTaskForm.detailedDescription" type="textarea" :rows="4" placeholder="详细描述故障现象、发生时间、位置等信息" /> | ||||
|           </el-form-item> | ||||
| @ -169,13 +173,31 @@ | ||||
|             <el-input v-model="createTaskForm.faultLocation" placeholder="例如:A区102" /> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="上传图片(可选)"> | ||||
|             <div class="upload-container"> | ||||
|               <div class="upload-box"> | ||||
|                 <i class="el-icon-plus avatar-uploader-icon"></i> | ||||
|                 <div class="upload-text">点击或拖拽图片至此处上传</div> | ||||
|                 <div class="upload-hint">支持JPG、PNG格式,最多3张</div> | ||||
|           <el-form-item label="上传图片(可选)" width="100%"> | ||||
|             <file-upload v-model="createTaskForm.file" :fileType="['png', 'jpg', 'jpeg']"> | ||||
|               <div class="upload-container"> | ||||
|                 <div class="upload-box"> | ||||
|                   <i class="el-icon-plus avatar-uploader-icon"></i> | ||||
|                   <div class="upload-text">点击或拖拽图片至此处上传</div> | ||||
|                   <div class="upload-hint">支持JPG、PNG格式,最多3张</div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </file-upload> | ||||
|             <!-- <el-upload | ||||
|               class="avatar-uploader" | ||||
|               :file-list="createTaskForm.fileList" | ||||
|               :on-change="handleFileChange" | ||||
|               :before-remove="beforeRemove" | ||||
|               :on-remove="handleRemove" | ||||
|               :auto-upload="false" | ||||
|               multiple | ||||
|               :limit="3" | ||||
|               :on-exceed="handleExceed" | ||||
|             > | ||||
|  | ||||
|             </el-upload> --> | ||||
|             <div v-if="createTaskForm.fileList && createTaskForm.fileList.length > 0" class="upload-tip"> | ||||
|               <span style="color: #1989fa">已选择{{ createTaskForm.fileList.length }}张图片,将在提交时上传</span> | ||||
|             </div> | ||||
|           </el-form-item> | ||||
|  | ||||
| @ -196,7 +218,7 @@ | ||||
|         <template #footer> | ||||
|           <span class="dialog-footer"> | ||||
|             <el-button @click="handleCancelCreateTask">取消</el-button> | ||||
|             <el-button type="primary" @click="handleSaveTask">保存计划</el-button> | ||||
|             <el-button type="primary" @click="handleSaveTask">保存报修任务</el-button> | ||||
|           </span> | ||||
|         </template> | ||||
|       </el-dialog> | ||||
| @ -205,10 +227,12 @@ | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { ref, computed } from 'vue'; | ||||
| import { ref, computed, onMounted } from 'vue'; | ||||
| import router from '@/router'; | ||||
| import TitleComponent from './TitleComponent.vue'; | ||||
|  | ||||
| import { baoxiulist, baoxiuDetail, delbaoxiu, updatebaoxiu, addbaoxiu, uploadbaoxiu } from '@/api/zhinengxunjian/baoxiou/index'; | ||||
| import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| // 激活的选项卡 | ||||
| const activeTab = ref('task'); | ||||
|  | ||||
| @ -217,128 +241,165 @@ const taskStatus = ref(''); | ||||
| const planType = ref(''); | ||||
| const executor = ref(''); | ||||
|  | ||||
| // 任务数据 - 恢复优先级标签样式和预计完成时间 | ||||
| const tasks = ref([ | ||||
|   { | ||||
|     title: '服务器A1电源故障', | ||||
|     status: 'executing', | ||||
|     statusText: '处理中', | ||||
|     leftLineClass: 'left-line-high', | ||||
|     priorityClass: 'priority-high', // 恢复优先级标签样式类 | ||||
|     priority: '高优先级', | ||||
|     reportTime: '2025-06-16 08:30', | ||||
|     reporter: '李明', | ||||
|     maintainer: '张明', | ||||
|     expectedCompleteTime: '2025-06-16 12:00', // 恢复预计完成时间 | ||||
|     actionText: '跟进', | ||||
|     actionClass: 'follow-btn' | ||||
|   }, | ||||
|   { | ||||
|     title: '机房环境检查', | ||||
|     status: 'pending', | ||||
|     statusText: '待处理', | ||||
|     leftLineClass: 'left-line-medium', | ||||
|     priorityClass: 'priority-medium', // 恢复优先级标签样式类 | ||||
|     priority: '中优先级', | ||||
|     reportTime: '2025-06-16 08:30', | ||||
|     reporter: '张伟', | ||||
|     maintainer: '未分配', | ||||
|     expectedCompleteTime: '2025-06-16 18:00', // 恢复预计完成时间 | ||||
|     actionText: '分配', | ||||
|     actionClass: 'assign-btn' | ||||
|   }, | ||||
|   { | ||||
|     title: '测试软件授权过期', | ||||
|     status: 'executing', | ||||
|     statusText: '处理中', | ||||
|     leftLineClass: 'left-line-low', | ||||
|     priorityClass: 'priority-low', // 恢复优先级标签样式类 | ||||
|     priority: '低优先级', | ||||
|     reportTime: '2025-06-16 08:30', | ||||
|     reporter: '李明', | ||||
|     maintainer: '李阳', | ||||
|     expectedCompleteTime: '2025-06-17 09:00', // 恢复预计完成时间 | ||||
|     actionText: '跟进', | ||||
|     actionClass: 'follow-btn' | ||||
|   }, | ||||
|   { | ||||
|     title: '打印机卡纸故障', | ||||
|     status: 'completed', | ||||
|     statusText: '已完成', | ||||
|     leftLineClass: 'left-line-completed', | ||||
|     priorityClass: 'priority-low', // 恢复优先级标签样式类 | ||||
|     priority: '低优先级', | ||||
|     reportTime: '2025-06-17 08:30', | ||||
|     reporter: '李明', | ||||
|     maintainer: '张明', | ||||
|     expectedCompleteTime: '2025-06-17 10:00', // 恢复预计完成时间 | ||||
|     completeTime: '2025-06-17 09:15', | ||||
|     actionText: '评价', | ||||
|     actionClass: 'evaluate-btn' | ||||
|   }, | ||||
|   { | ||||
|     title: '服务器A1电源故障', | ||||
|     status: 'executing', | ||||
|     statusText: '处理中', | ||||
|     leftLineClass: 'left-line-high', | ||||
|     priorityClass: 'priority-high', | ||||
|     priority: '高优先级', | ||||
|     reportTime: '2025-06-16 08:30', | ||||
|     reporter: '李明', | ||||
|     maintainer: '张明', | ||||
|     expectedCompleteTime: '2025-06-16 12:00', | ||||
|     actionText: '跟进', | ||||
|     actionClass: 'follow-btn' | ||||
|   }, | ||||
|   { | ||||
|     title: '机房环境检查', | ||||
|     status: 'pending', | ||||
|     statusText: '待处理', | ||||
|     leftLineClass: 'left-line-medium', | ||||
|     priorityClass: 'priority-medium', | ||||
|     priority: '中优先级', | ||||
|     reportTime: '2025-06-16 08:30', | ||||
|     reporter: '张伟', | ||||
|     maintainer: '未分配', | ||||
|     expectedCompleteTime: '2025-06-16 18:00', | ||||
|     actionText: '分配', | ||||
|     actionClass: 'assign-btn' | ||||
|   }, | ||||
|   { | ||||
|     title: '测试软件授权过期', | ||||
|     status: 'executing', | ||||
|     statusText: '处理中', | ||||
|     leftLineClass: 'left-line-low', | ||||
|     priorityClass: 'priority-low', | ||||
|     priority: '低优先级', | ||||
|     reportTime: '2025-06-16 08:30', | ||||
|     reporter: '李明', | ||||
|     maintainer: '李阳', | ||||
|     expectedCompleteTime: '2025-06-17 09:00', | ||||
|     actionText: '跟进', | ||||
|     actionClass: 'follow-btn' | ||||
|   }, | ||||
|   { | ||||
|     title: '打印机卡纸故障', | ||||
|     status: 'completed', | ||||
|     statusText: '已完成', | ||||
|     leftLineClass: 'left-line-completed', | ||||
|     priorityClass: 'priority-low', | ||||
|     priority: '低优先级', | ||||
|     reportTime: '2025-06-17 08:30', | ||||
|     reporter: '李明', | ||||
|     maintainer: '张明', | ||||
|     expectedCompleteTime: '2025-06-17 10:00', | ||||
|     completeTime: '2025-06-17 09:15', | ||||
|     actionText: '评价', | ||||
|     actionClass: 'evaluate-btn' | ||||
|   } | ||||
| ]); | ||||
| // 任务数据 - 初始为空数组 | ||||
| const tasks = ref([]); | ||||
|  | ||||
| // 分页相关 | ||||
| const currentPage = ref(1); | ||||
| const pageSize = ref(8); | ||||
| const total = ref(tasks.value.length); | ||||
| const total = ref(0); | ||||
| const loading = ref(false); | ||||
|  | ||||
| // 获取报修任务列表 | ||||
| defineExpose({ getTaskList }); | ||||
| async function getTaskList() { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     const res = await baoxiulist({ | ||||
|       pageNum: currentPage.value, | ||||
|       pageSize: pageSize.value, | ||||
|       status: taskStatus.value, | ||||
|       type: planType.value, | ||||
|       executor: executor.value | ||||
|     }); | ||||
|  | ||||
|     if (res.code === 200 && res.rows) { | ||||
|       total.value = res.total || 0; | ||||
|       // 将API返回的数据转换为前端显示所需的格式 | ||||
|       tasks.value = res.rows.map((item) => ({ | ||||
|         id: item.id, | ||||
|         title: item.name || '未命名报修任务', | ||||
|         status: mapStatusToKey(item.status), | ||||
|         statusText: getStatusText(item.status), | ||||
|         leftLineClass: getLeftLineClass(item.status, item.level), | ||||
|         priorityClass: getPriorityClass(item.level), | ||||
|         priority: getPriorityText(item.level), | ||||
|         reportTime: formatDate(item.reportTime), | ||||
|         reporter: item.reportName || '未知报修人', | ||||
|         maintainer: item.sendPerson ? `维修人ID: ${item.sendPerson}` : '未分配', | ||||
|         expectedCompleteTime: getExpectedCompleteTime(item.status), | ||||
|         completeTime: item.completeTime ? formatDate(item.completeTime) : '', | ||||
|         actionText: getActionText(item.status), | ||||
|         actionClass: getActionClass(item.status), | ||||
|         reportInfo: item.reportInfo, | ||||
|         position: item.position, | ||||
|         fileUrl: item.fileUrl | ||||
|       })); | ||||
|     } else { | ||||
|       tasks.value = []; | ||||
|       total.value = 0; | ||||
|       console.error('获取报修任务列表失败:', res.msg); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('获取报修任务列表异常:', error); | ||||
|     tasks.value = []; | ||||
|     total.value = 0; | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // 状态映射辅助函数 | ||||
| function mapStatusToKey(status) { | ||||
|   const statusMap = { | ||||
|     '1': 'pending', // 待处理 | ||||
|     '2': 'executing', // 处理中 | ||||
|     '3': 'completed' // 已完成 | ||||
|   }; | ||||
|   return statusMap[status] || 'pending'; | ||||
| } | ||||
|  | ||||
| // 获取状态文本 | ||||
| function getStatusText(status) { | ||||
|   const statusMap = { | ||||
|     '1': '待处理', | ||||
|     '2': '处理中', | ||||
|     '3': '已完成' | ||||
|   }; | ||||
|   return statusMap[status] || '未知状态'; | ||||
| } | ||||
|  | ||||
| // 获取优先级文本 | ||||
| function getPriorityText(level) { | ||||
|   const levelMap = { | ||||
|     '1': '低优先级', | ||||
|     '2': '中优先级', | ||||
|     '3': '高优先级' | ||||
|   }; | ||||
|   return levelMap[level] || '普通优先级'; | ||||
| } | ||||
|  | ||||
| // 获取优先级样式类 | ||||
| function getPriorityClass(level) { | ||||
|   const levelMap = { | ||||
|     '1': 'priority-low', | ||||
|     '2': 'priority-medium', | ||||
|     '3': 'priority-high' | ||||
|   }; | ||||
|   return levelMap[level] || 'priority-low'; | ||||
| } | ||||
|  | ||||
| // 获取左侧状态线样式类 | ||||
| function getLeftLineClass(status, level) { | ||||
|   if (status === '3') return 'left-line-completed'; | ||||
|  | ||||
|   const levelMap = { | ||||
|     '1': 'left-line-low', | ||||
|     '2': 'left-line-medium', | ||||
|     '3': 'left-line-high' | ||||
|   }; | ||||
|   return levelMap[level] || 'left-line-low'; | ||||
| } | ||||
|  | ||||
| // 获取操作按钮文本 | ||||
| function getActionText(status) { | ||||
|   const actionMap = { | ||||
|     '1': '分配', | ||||
|     '2': '跟进', | ||||
|     '3': '评价' | ||||
|   }; | ||||
|   return actionMap[status] || '查看'; | ||||
| } | ||||
|  | ||||
| // 获取操作按钮样式类 | ||||
| function getActionClass(status) { | ||||
|   const actionMap = { | ||||
|     '1': 'assign-btn', | ||||
|     '2': 'follow-btn', | ||||
|     '3': 'evaluate-btn' | ||||
|   }; | ||||
|   return actionMap[status] || 'view-btn'; | ||||
| } | ||||
|  | ||||
| // 获取预计完成时间(根据状态和优先级估算) | ||||
| function getExpectedCompleteTime(status) { | ||||
|   if (status === '3') return ''; // 已完成任务不需要显示预计时间 | ||||
|  | ||||
|   const now = new Date(); | ||||
|   // 简单估算:待处理任务默认当天18:00前完成,处理中任务默认2小时内完成 | ||||
|   if (status === '1') { | ||||
|     now.setHours(18, 0, 0, 0); | ||||
|   } else { | ||||
|     now.setHours(now.getHours() + 2); | ||||
|   } | ||||
|   return formatDate(now); | ||||
| } | ||||
|  | ||||
| // 格式化日期时间 | ||||
| function formatDate(date) { | ||||
|   if (!date) return ''; | ||||
|  | ||||
|   const d = new Date(date); | ||||
|   if (isNaN(d.getTime())) return ''; | ||||
|  | ||||
|   const year = d.getFullYear(); | ||||
|   const month = String(d.getMonth() + 1).padStart(2, '0'); | ||||
|   const day = String(d.getDate()).padStart(2, '0'); | ||||
|   const hours = String(d.getHours()).padStart(2, '0'); | ||||
|   const minutes = String(d.getMinutes()).padStart(2, '0'); | ||||
|  | ||||
|   return `${year}-${month}-${day} ${hours}:${minutes}`; | ||||
| } | ||||
|  | ||||
| // 状态排序映射 | ||||
| const statusOrder = { | ||||
| @ -363,20 +424,22 @@ const pagedTasks = computed(() => { | ||||
| // 搜索处理 | ||||
| const handleSearch = () => { | ||||
|   currentPage.value = 1; // 重置到第一页 | ||||
|   // 实际应用中这里会根据筛选条件过滤数据 | ||||
|   getTaskList(); // 调用接口获取数据 | ||||
| }; | ||||
|  | ||||
| // 创建报修任务弹窗相关 | ||||
| const createTaskDialogVisible = ref(false); | ||||
| const createTaskFormRef = ref(null); | ||||
| const createTaskForm = ref({ | ||||
|   repairName: '', | ||||
|   briefDescription: '', | ||||
|   repairType: '', | ||||
|   priority: '', | ||||
|   detailedDescription: '', | ||||
|   faultLocation: '', | ||||
|   contactPerson: '', | ||||
|   contactPhone: '' | ||||
|   contactPhone: '', | ||||
|   sendPerson: '', // 指派维修人 | ||||
|   file: '' // 上传的文件列表 | ||||
| }); | ||||
|  | ||||
| const createTaskRules = { | ||||
| @ -386,58 +449,303 @@ const createTaskRules = { | ||||
|   detailedDescription: [{ required: true, message: '请输入详细描述', trigger: 'blur' }], | ||||
|   faultLocation: [{ required: true, message: '请输入故障位置', trigger: 'blur' }], | ||||
|   contactPerson: [{ required: true, message: '请输入联系人', trigger: 'blur' }], | ||||
|   contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }] | ||||
|   contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }], | ||||
|   sendPerson: [{ required: true, message: '请选择维修人', trigger: 'change' }] | ||||
| }; | ||||
|  | ||||
| // 用户列表(维修人) | ||||
| const usersList = ref([]); | ||||
| const loadingUsers = ref(false); | ||||
|  | ||||
| // 获取用户列表 | ||||
| const getUsersList = async () => { | ||||
|   loadingUsers.value = true; | ||||
|   try { | ||||
|     const res = await xunjianUserlist(); | ||||
|     // 根据接口返回格式,成功码是200,用户数据在rows数组中 | ||||
|     if (res.code === 200 && res.rows && Array.isArray(res.rows)) { | ||||
|       // 映射用户数据,使用id作为value,userName作为显示名称 | ||||
|       usersList.value = res.rows.map((user) => ({ | ||||
|         id: user.id, | ||||
|         name: user.userName | ||||
|       })); | ||||
|     } else { | ||||
|       usersList.value = []; | ||||
|       console.error('获取用户列表失败:', res.msg || '未知错误'); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('获取用户列表异常:', error); | ||||
|     usersList.value = []; | ||||
|   } finally { | ||||
|     loadingUsers.value = false; | ||||
|   } | ||||
| }; | ||||
| const isSubmitting = ref(false); // 防止重复提交的状态标记 | ||||
| const isUploading = ref(false); // 防止重复上传的状态标记 | ||||
| // 上传文件方法 | ||||
| const uploadFiles = async (files) => { | ||||
|   // 防止重复上传 | ||||
|   if (isUploading.value) { | ||||
|     ElMessage.warning('数据正在处理中,请稍候...'); | ||||
|     return []; | ||||
|   } | ||||
|  | ||||
|   try { | ||||
|     isUploading.value = true; | ||||
|     const formData = new FormData(); | ||||
|  | ||||
|     // 关键修复:将字段名从'files'改为'file',匹配后端要求的'file'字段 | ||||
|     files.forEach((file) => { | ||||
|       formData.append('file', file.raw); // 这里将'files'改为'file' | ||||
|     }); | ||||
|  | ||||
|     const res = await uploadbaoxiu(formData); | ||||
|  | ||||
|     if (res.code === 200 && res.data && Array.isArray(res.data)) { | ||||
|       return res.data.map((item) => ({ | ||||
|         fileId: item.ossId, | ||||
|         fileUrl: item.url | ||||
|       })); | ||||
|     } else { | ||||
|       console.error('文件上传失败:', res.msg); | ||||
|       throw new Error(res.msg || '文件上传失败'); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('文件上传异常:', error); | ||||
|     if (error.message.includes('重复提交')) { | ||||
|       throw new Error('操作过于频繁,请稍后再试'); | ||||
|     } | ||||
|     throw error; | ||||
|   } finally { | ||||
|     isUploading.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const handleFileChange = (file, fileList) => { | ||||
|   // 只处理刚添加的文件 | ||||
|   if (file.status === 'ready') { | ||||
|     // 验证文件格式和大小 | ||||
|     const isJPG = file.raw.type === 'image/jpeg' || file.raw.type === 'image/jpg'; | ||||
|     const isPNG = file.raw.type === 'image/png'; | ||||
|     const isLt2M = file.size / 1024 / 1024 < 2; | ||||
|  | ||||
|     if (!isJPG && !isPNG) { | ||||
|       ElMessage.error('上传图片只能是 JPG/JPEG 或 PNG 格式!'); | ||||
|       // 从文件列表中移除不符合要求的文件 | ||||
|       createTaskForm.value.fileList = fileList.filter((f) => f.uid !== file.uid); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (!isLt2M) { | ||||
|       ElMessage.error('上传图片大小不能超过 2MB!'); | ||||
|       // 从文件列表中移除不符合要求的文件 | ||||
|       createTaskForm.value.fileList = fileList.filter((f) => f.uid !== file.uid); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     // 保存验证通过的文件到表单 | ||||
|     createTaskForm.value.fileList = fileList; | ||||
|   } | ||||
| }; | ||||
| const handleExceed = (files, fileList) => { | ||||
|   ElMessage.warning(`当前限制选择 3 张图片,本次选择了 ${files.length} 张,共选择了 ${files.length + fileList.length} 张`); | ||||
| }; | ||||
|  | ||||
| // 文件移除前的钩子 | ||||
| const beforeRemove = (file, fileList) => { | ||||
|   return window.confirm(`确定移除 ${file.name}?`); | ||||
| }; | ||||
|  | ||||
| // 文件移除时的钩子 | ||||
| const handleRemove = (file, fileList) => { | ||||
|   createTaskForm.value.fileList = fileList; | ||||
|   ElMessage.info(`已移除 ${file.name}`); | ||||
| }; | ||||
| // 创建任务 | ||||
| const handleCreateTask = () => { | ||||
| const handleCreateTask = async () => { | ||||
|   createTaskDialogVisible.value = true; | ||||
|   // 打开弹窗时获取用户列表 | ||||
|   await getUsersList(); | ||||
| }; | ||||
|  | ||||
| // 保存报修任务 | ||||
| const handleSaveTask = () => { | ||||
|   // 模拟保存报修任务逻辑 | ||||
|   console.log('保存报修任务:', createTaskForm.value); | ||||
|   // 关闭弹窗 | ||||
|   createTaskDialogVisible.value = false; | ||||
|   // 重置表单 | ||||
| const handleSaveTask = async () => { | ||||
|   console.log(createTaskForm.value.file); | ||||
|   // 防止重复提交 | ||||
|   if (!createTaskFormRef.value || isSubmitting.value) return; | ||||
|  | ||||
|   try { | ||||
|     // 设置提交状态为true | ||||
|     isSubmitting.value = true; | ||||
|  | ||||
|     // 先验证表单 | ||||
|     await createTaskFormRef.value.validate(); | ||||
|     // 上传选中的文件 | ||||
|     let fileIds = []; | ||||
|     let fileUrls = []; | ||||
|  | ||||
|     if (createTaskForm.value.fileList && createTaskForm.value.fileList.length > 0) { | ||||
|       ElMessage.info(`开始上传 ${createTaskForm.value.fileList.length} 张图片...`); | ||||
|       const uploadResults = await uploadFiles(createTaskForm.value.fileList); | ||||
|  | ||||
|       // 提取上传结果 | ||||
|       fileIds = uploadResults.map((result) => result.fileId); | ||||
|       fileUrls = uploadResults.map((result) => result.fileUrl); | ||||
|  | ||||
|       ElMessage.success(`图片上传成功,共 ${uploadResults.length} 张`); | ||||
|     } | ||||
|  | ||||
|     // 准备请求数据 | ||||
|     const requestData = { | ||||
|       projectId: 1, | ||||
|       name: createTaskForm.value.repairName, | ||||
|       type: mapRepairType(createTaskForm.value.repairType), | ||||
|       status: '1', // 默认为待处理状态 | ||||
|       level: mapPriorityLevel(createTaskForm.value.priority), | ||||
|       sendPerson: parseInt(createTaskForm.value.sendPerson), | ||||
|       reportInfo: createTaskForm.value.detailedDescription, | ||||
|       position: createTaskForm.value.faultLocation, | ||||
|       fileId: fileIds.join(','), // 用逗号分隔多个文件ID | ||||
|       fileUrl: fileUrls.join(','), // 用逗号分隔多个文件URL | ||||
|       reportName: createTaskForm.value.contactPerson, | ||||
|       reportPhone: createTaskForm.value.contactPhone | ||||
|     }; | ||||
|  | ||||
|     // 调用添加报修任务接口 | ||||
|     const res = await addbaoxiu(requestData); | ||||
|  | ||||
|     // 检查接口返回是否成功(使用code=200作为成功标志) | ||||
|     if (res.code === 200) { | ||||
|       // 显示成功提示 | ||||
|       ElMessage.success('报修任务创建成功'); | ||||
|  | ||||
|       // 关闭弹窗 | ||||
|       createTaskDialogVisible.value = false; | ||||
|  | ||||
|       // 重置表单 | ||||
|       resetCreateForm(); | ||||
|  | ||||
|       // 刷新任务列表 | ||||
|       await getTaskList(); | ||||
|     } else { | ||||
|       ElMessage.error(`创建失败:${res.msg || '未知错误'}`); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     // 错误处理 | ||||
|     if (error instanceof Error) { | ||||
|       ElMessage.error(`操作失败:${error.message}`); | ||||
|     } else if (error === false) { | ||||
|       // 表单验证失败,不做处理 | ||||
|     } else { | ||||
|       ElMessage.error('操作失败:未知错误'); | ||||
|     } | ||||
|   } finally { | ||||
|     // 无论成功失败,都重置提交状态 | ||||
|     isSubmitting.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // 重置创建表单 | ||||
| function resetCreateForm() { | ||||
|   createTaskForm.value = { | ||||
|     repairName: '', | ||||
|     briefDescription: '', | ||||
|     repairType: '', | ||||
|     priority: '', | ||||
|     detailedDescription: '', | ||||
|     faultLocation: '', | ||||
|     contactPerson: '', | ||||
|     contactPhone: '' | ||||
|     contactPhone: '', | ||||
|     sendPerson: '', | ||||
|     fileList: [] | ||||
|   }; | ||||
|   // 这里可以添加成功提示和刷新任务列表的逻辑 | ||||
| }; | ||||
|  | ||||
|   if (createTaskFormRef.value) { | ||||
|     createTaskFormRef.value.resetFields(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // 报修类型映射 - 1硬件2软件 | ||||
| function mapRepairType(type) { | ||||
|   const typeMap = { | ||||
|     'device': '1', // 硬件 | ||||
|     'software': '2' // 软件 | ||||
|   }; | ||||
|   return typeMap[type] || '1'; | ||||
| } | ||||
|  | ||||
| // 优先级映射 - 1低优先2中优先3高优先 | ||||
| function mapPriorityLevel(priority) { | ||||
|   const levelMap = { | ||||
|     'low': '1', // 低优先 | ||||
|     'medium': '2', // 中优先 | ||||
|     'high': '3' // 高优先 | ||||
|   }; | ||||
|   return levelMap[priority] || '2'; | ||||
| } | ||||
|  | ||||
| // 文件上传前的校验 | ||||
| async function beforeUpload(file) { | ||||
|   const isJPG = file.type === 'image/jpeg' || file.type === 'image/jpg'; | ||||
|   const isPNG = file.type === 'image/png'; | ||||
|   const isLt2M = file.size / 1024 / 1024 < 2; | ||||
|  | ||||
|   if (!isJPG && !isPNG) { | ||||
|     ElMessage.error('上传图片只能是 JPG/JPEG 或 PNG 格式!'); | ||||
|     return false; | ||||
|   } | ||||
|   if (!isLt2M) { | ||||
|     ElMessage.error('上传图片大小不能超过 2MB!'); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   try { | ||||
|     // 直接上传文件 | ||||
|     const uploadResult = await uploadFile(file); | ||||
|     // 存储文件信息到表单 | ||||
|     createTaskForm.value.fileList = [ | ||||
|       { | ||||
|         ...file, | ||||
|         fileId: uploadResult.fileId, | ||||
|         fileUrl: uploadResult.fileUrl | ||||
|       } | ||||
|     ]; | ||||
|     ElMessage.success('图片上传成功'); | ||||
|   } catch (error) { | ||||
|     ElMessage.error('图片上传失败,请重试'); | ||||
|   } | ||||
|  | ||||
|   // 阻止自动上传 | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| // 文件上传成功处理 | ||||
| function handleUploadSuccess(response, file, fileList) { | ||||
|   // 这个函数实际上不会被调用,因为auto-upload=false | ||||
|   // 真正的上传逻辑在beforeUpload函数中处理 | ||||
| } | ||||
|  | ||||
| // 文件上传失败处理 | ||||
| function handleUploadError(err, file, fileList) { | ||||
|   ElMessage.error('上传失败,请稍后重试'); | ||||
| } | ||||
|  | ||||
| // 取消创建报修任务 | ||||
| const handleCancelCreateTask = () => { | ||||
|   createTaskDialogVisible.value = false; | ||||
|   // 重置表单 | ||||
|   createTaskForm.value = { | ||||
|     repairName: '', | ||||
|     briefDescription: '', | ||||
|     repairType: '', | ||||
|     priority: '', | ||||
|     detailedDescription: '', | ||||
|     faultLocation: '', | ||||
|     contactPerson: '', | ||||
|     contactPhone: '' | ||||
|   }; | ||||
|   resetCreateForm(); | ||||
| }; | ||||
|  | ||||
| // 分页事件 | ||||
| const handleSizeChange = (val) => { | ||||
|   pageSize.value = val; | ||||
|   currentPage.value = 1; | ||||
|   getTaskList(); // 重新获取数据 | ||||
| }; | ||||
|  | ||||
| const handleCurrentChange = (val) => { | ||||
|   currentPage.value = val; | ||||
|   getTaskList(); // 重新获取数据 | ||||
| }; | ||||
|  | ||||
| // 查看任务详情 | ||||
| @ -478,6 +786,12 @@ const handleInspection6 = () => { | ||||
| const handleInspection7 = () => { | ||||
|   router.push('/rili/renyuanzhuangtai'); | ||||
| }; | ||||
|  | ||||
| // 组件挂载时获取数据 | ||||
| onMounted(async () => { | ||||
|   // 只获取任务列表,用户列表在弹窗打开时获取 | ||||
|   await getTaskList(); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
| @ -824,28 +1138,10 @@ const handleInspection7 = () => { | ||||
|   flex-shrink: 0; | ||||
| } | ||||
|  | ||||
| .search-btn { | ||||
|   background-color: #f2f3f5; | ||||
|   color: #303133; | ||||
|   border-color: #f2f3f5; | ||||
|   transition: all 0.2s ease; | ||||
| } | ||||
|  | ||||
| .search-btn:hover { | ||||
|   background-color: #e5e6eb; | ||||
|   color: #303133; | ||||
|   border-color: #e5e6eb; | ||||
| } | ||||
|  | ||||
| .search-btn, | ||||
| .create-btn { | ||||
|   background-color: #165dff; | ||||
|   border-color: #165dff; | ||||
|   transition: all 0.2s ease; | ||||
| } | ||||
|  | ||||
| .create-btn:hover { | ||||
|   background-color: #0e42d2; | ||||
|   border-color: #0e42d2; | ||||
|   height: 36px; | ||||
|   border-radius: 4px; | ||||
| } | ||||
|  | ||||
| /* 任务卡片样式 - 恢复优先级标签背景色 */ | ||||
| @ -1073,6 +1369,24 @@ const handleInspection7 = () => { | ||||
|   color: #fff; | ||||
| } | ||||
|  | ||||
| .avatar-uploader .el-upload-list { | ||||
|   margin-top: 12px; | ||||
| } | ||||
|  | ||||
| .avatar-uploader .el-upload-list__item { | ||||
|   border-radius: 6px; | ||||
|   margin-bottom: 8px; | ||||
|   transition: all 0.2s; | ||||
| } | ||||
|  | ||||
| .avatar-uploader .el-upload-list__item:hover { | ||||
|   transform: translateX(4px); | ||||
| } | ||||
|  | ||||
| .upload-tip { | ||||
|   margin-top: 10px; | ||||
|   font-size: 12px; | ||||
| } | ||||
| /* 响应式设计 */ | ||||
| @media (max-width: 1200px) { | ||||
|   .task-cards { | ||||
|  | ||||
| @ -11,12 +11,6 @@ | ||||
|         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||
|         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||
|       </div> | ||||
|  | ||||
|       <!-- 标题栏 --> | ||||
|       <div class="header"> | ||||
|         <TitleComponent title="运维待办事项" subtitle="管理每日、每周等的运维工作任务"></TitleComponent> | ||||
|       </div> | ||||
|  | ||||
|       <div class="main-content"> | ||||
|         <!-- 左侧日历区域 --> | ||||
|         <div class="calendar-container"> | ||||
| @ -105,7 +99,13 @@ | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <el-dialog v-model="dialogVisible" title="新增任务" width="480px" class="custom-dialog" :before-close="closeDialog"> | ||||
|       <el-dialog | ||||
|         v-model="dialogVisible" | ||||
|         :title="editingTaskId ? '编辑任务' : '新增任务'" | ||||
|         width="480px" | ||||
|         class="custom-dialog" | ||||
|         :before-close="closeDialog" | ||||
|       > | ||||
|         <el-form :model="taskForm" label-width="80px" class="task-form"> | ||||
|           <el-form-item label="任务名称" prop="name"> | ||||
|             <el-input v-model="taskForm.name" placeholder="输入任务名称" class="form-input"></el-input> | ||||
| @ -119,6 +119,7 @@ | ||||
|               type="datetimerange" | ||||
|               start-placeholder="开始时间" | ||||
|               end-placeholder="结束时间" | ||||
|               :disabled-date="() => false" | ||||
|               class="form-input" | ||||
|               style="width: 100%" | ||||
|             /> | ||||
| @ -139,7 +140,7 @@ | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|           <!-- 新增:工作时间段选择器 --> | ||||
|           <el-form-item label="工作时间段1" prop="workTimeRange1"> | ||||
|           <el-form-item label="开始时间" prop="workTimeRange1"> | ||||
|             <el-time-picker | ||||
|               v-model="taskForm.workTimeRange1" | ||||
|               type="timerange" | ||||
| @ -151,7 +152,7 @@ | ||||
|               style="width: 100%" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="工作时间段2" prop="workTimeRange2"> | ||||
|           <el-form-item label="结束时间" prop="workTimeRange2"> | ||||
|             <el-time-picker | ||||
|               v-model="taskForm.workTimeRange2" | ||||
|               type="timerange" | ||||
| @ -176,7 +177,6 @@ | ||||
| <script setup> | ||||
| import { ref, computed, watch, onMounted } from 'vue'; | ||||
| import router from '@/router'; | ||||
| import TitleComponent from './TitleComponent.vue'; | ||||
| import { daibanlist, adddaiban, updatedaiban, deldaiban } from '@/api/zhinengxunjian/daiban/index'; | ||||
|  | ||||
| // 默认显示当前月份 | ||||
| @ -442,93 +442,17 @@ const saveTask = async () => { | ||||
|     if (editingTaskId.value) { | ||||
|       // 编辑操作 - 修改参数传递方式,将id合并到apiData中 | ||||
|       response = await updatedaiban({ ...apiData, id: editingTaskId.value }); | ||||
|  | ||||
|       // 更新本地数据 | ||||
|       const index = todoListData.value.findIndex((item) => item.id === editingTaskId.value); | ||||
|       if (index !== -1) { | ||||
|         todoListData.value[index] = { | ||||
|           ...todoListData.value[index], | ||||
|           title: taskForm.value.name, | ||||
|           describeValue: taskForm.value.describeValue, | ||||
|           timeRange: formatTimeRange(taskForm.value.timeRange[0], taskForm.value.timeRange[1]), | ||||
|           originalTimeRange: taskForm.value.timeRange, | ||||
|           taskLevel: taskForm.value.taskLevel, | ||||
|           taskType: taskForm.value.taskType, | ||||
|           // 保留原有字段以便前端显示,添加类型检查 | ||||
|           workTimeRange1: taskForm.value.workTimeRange1 | ||||
|             ? Array.isArray(taskForm.value.workTimeRange1) | ||||
|               ? taskForm.value.workTimeRange1.join('-') | ||||
|               : taskForm.value.workTimeRange1 | ||||
|             : '', | ||||
|           workTimeRange2: taskForm.value.workTimeRange2 | ||||
|             ? Array.isArray(taskForm.value.workTimeRange2) | ||||
|               ? taskForm.value.workTimeRange2.join('-') | ||||
|               : taskForm.value.workTimeRange2 | ||||
|             : '' | ||||
|         }; | ||||
|       } | ||||
|  | ||||
|       // 更新日历事件 | ||||
|       const eventIndex = calendarEvents.value.findIndex((item) => item.id === editingTaskId.value); | ||||
|       if (eventIndex !== -1) { | ||||
|         calendarEvents.value[eventIndex] = { | ||||
|           ...calendarEvents.value[eventIndex], | ||||
|           title: taskForm.value.name, | ||||
|           describeValue: taskForm.value.describeValue, | ||||
|           type: getEventType(taskForm.value.taskType) | ||||
|         }; | ||||
|       } | ||||
|  | ||||
|       ElMessage.success('任务更新成功'); | ||||
|     } else { | ||||
|       // 新增操作 | ||||
|       response = await adddaiban(apiData); | ||||
|       console.log('保存任务成功:', response); | ||||
|  | ||||
|       // 获取当前日期 | ||||
|       const currentDateStr = formatDate(new Date()); | ||||
|  | ||||
|       // 从接口响应中获取任务ID(如果返回) | ||||
|       const newId = response.data?.id || Date.now(); | ||||
|  | ||||
|       // 构建新任务对象添加到本地数据中 | ||||
|       const newTask = { | ||||
|         id: newId, | ||||
|         title: taskForm.value.name, | ||||
|         describeValue: taskForm.value.describeValue, | ||||
|         timeRange: formatTimeRange(taskForm.value.timeRange[0], taskForm.value.timeRange[1]), | ||||
|         originalTimeRange: taskForm.value.timeRange, | ||||
|         taskLevel: taskForm.value.taskLevel, | ||||
|         taskType: taskForm.value.taskType, | ||||
|         // 保留原有字段以便前端显示,添加类型检查 | ||||
|         workTimeRange1: taskForm.value.workTimeRange1 | ||||
|           ? Array.isArray(taskForm.value.workTimeRange1) | ||||
|             ? taskForm.value.workTimeRange1.join('-') | ||||
|             : taskForm.value.workTimeRange1 | ||||
|           : '', | ||||
|         workTimeRange2: taskForm.value.workTimeRange2 | ||||
|           ? Array.isArray(taskForm.value.workTimeRange2) | ||||
|             ? taskForm.value.workTimeRange2.join('-') | ||||
|             : taskForm.value.workTimeRange2 | ||||
|           : '', | ||||
|         date: currentDateStr | ||||
|       }; | ||||
|  | ||||
|       // 添加到待办列表 | ||||
|       todoListData.value.unshift(newTask); | ||||
|  | ||||
|       // 添加到日历事件 | ||||
|       calendarEvents.value.push({ | ||||
|         id: newId, | ||||
|         date: currentDateStr, | ||||
|         title: taskForm.value.name, | ||||
|         describeValue: taskForm.value.describeValue, | ||||
|         type: getEventType(taskForm.value.taskType) | ||||
|       }); | ||||
|  | ||||
|       ElMessage.success('任务添加成功'); | ||||
|     } | ||||
|  | ||||
|     // 重新从接口获取最新数据,确保列表数据与后端保持一致 | ||||
|     await fetchData(); | ||||
|  | ||||
|     // 重置表单 | ||||
|     taskForm.value = { | ||||
|       name: '', | ||||
| @ -622,9 +546,8 @@ const handleDelete = (id) => { | ||||
|         // 接口要求格式: /ops/matter/{ids},这里ids是单个ID | ||||
|         await deldaiban(id); | ||||
|  | ||||
|         // 前端删除同步 | ||||
|         todoListData.value = todoListData.value.filter((item) => item.id !== id); | ||||
|         calendarEvents.value = calendarEvents.value.filter((item) => item.id !== id); | ||||
|         // 删除成功后重新获取最新数据 | ||||
|         await fetchData(); | ||||
|         ElMessage.success('任务已删除'); | ||||
|       } catch (error) { | ||||
|         console.error('删除任务失败:', error); | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -12,7 +12,6 @@ | ||||
|       </div> | ||||
|  | ||||
|       <div class="header-container"> | ||||
|         <TitleComponent title="实验管理系统" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent> | ||||
|         <div class="header-actions"> | ||||
|           <el-button type="primary" class="export-btn">筛选</el-button> | ||||
|           <el-button type="primary" class="create-btn">导入数据</el-button> | ||||
| @ -278,7 +277,7 @@ | ||||
| <script setup> | ||||
| import { ref, computed } from 'vue'; | ||||
| import router from '@/router'; | ||||
| import TitleComponent from './TitleComponent.vue'; | ||||
|  | ||||
| // 1. 选项卡状态管理 | ||||
| const activeTab = ref('record'); // 默认显示"巡检记录" | ||||
| const showFilter = ref(false); | ||||
| @ -360,35 +359,41 @@ const handleInspectionManagement3 = () => { | ||||
|   min-height: 100vh; | ||||
| } | ||||
|  | ||||
| /* 2. 顶部导航选项卡 */ | ||||
| /* 导航栏样式 */ | ||||
| .navigation-tabs { | ||||
|   display: flex; | ||||
|   margin-bottom: 20px; | ||||
|   background-color: #fff; | ||||
|   border-radius: 4px; | ||||
|   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||
|   margin-bottom: 20px; | ||||
|   overflow: hidden; | ||||
|   padding: 2px; | ||||
| } | ||||
|  | ||||
| .nav-tab { | ||||
|   padding: 12px 24px; | ||||
|   cursor: pointer; | ||||
|   transition: all 0.2s; | ||||
|   transition: all 0.3s ease; | ||||
|   border-radius: 4px; | ||||
|   font-size: 14px; | ||||
|   color: #6b7280; | ||||
|   color: #606266; | ||||
|   border-right: 1px solid #f0f0f0; | ||||
|   flex: 1; | ||||
|   text-align: center; | ||||
|   border-right: 1px solid #f0f0f0; | ||||
| } | ||||
|  | ||||
| .nav-tab:last-child { | ||||
|   border-right: none; | ||||
| } | ||||
| .nav-tab:hover:not(.active) { | ||||
|   background-color: #f3f4f6; | ||||
|  | ||||
| .nav-tab:hover { | ||||
|   color: #409eff; | ||||
|   background-color: #ecf5ff; | ||||
| } | ||||
|  | ||||
| .nav-tab.active { | ||||
|   background-color: #165dff; | ||||
|   background-color: #409eff; | ||||
|   color: #fff; | ||||
|   font-weight: 500; | ||||
|   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||
| } | ||||
|  | ||||
| /* 选项卡样式 */ | ||||
| @ -457,8 +462,8 @@ const handleInspectionManagement3 = () => { | ||||
| } | ||||
| .search-btn, | ||||
| .export-btn { | ||||
|   background-color: #165dff; | ||||
|   border-color: #165dff; | ||||
|   height: 36px; | ||||
|   border-radius: 4px; | ||||
| } | ||||
| .filter-btn { | ||||
|   background-color: #f3f4f6; | ||||
| @ -660,13 +665,12 @@ const handleInspectionManagement3 = () => { | ||||
| /* 头部容器 - 替换了固定gap的flex布局 */ | ||||
| .header-container { | ||||
|   display: flex; | ||||
|   justify-content: space-between; | ||||
|   justify-content: flex-end; | ||||
|   align-items: center; | ||||
| } | ||||
|  | ||||
| .header-actions { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   gap: 10px; | ||||
| } | ||||
| /* 12. 统计卡片样式 */ | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -10,10 +10,9 @@ | ||||
|       <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||
|     </div> | ||||
|     <div class="header-container"> | ||||
|       <TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent> | ||||
|       <div class="header-actions"> | ||||
|         <el-button type="primary" class="export-btn">筛选</el-button> | ||||
|         <el-button type="primary" class="create-btn">导入数据</el-button> | ||||
|         <el-button type="primary" class="create-btn">导出数据</el-button> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
| @ -364,9 +363,10 @@ | ||||
| <script setup> | ||||
| import { ref, onMounted, computed, onUnmounted } from 'vue'; | ||||
| import router from '@/router'; | ||||
| import TitleComponent from './TitleComponent.vue'; | ||||
| import * as echarts from 'echarts'; | ||||
|  | ||||
| import * as echarts from 'echarts'; | ||||
| import { xunjianjilu } from '@/api/zhinengxunjian/xunjian/jilu'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| // 筛选条件 | ||||
| const filterStatus = ref('all'); | ||||
| const filterType = ref('all'); | ||||
| @ -485,91 +485,70 @@ const handleTimeRangeChange = (range) => { | ||||
|   fetchDashboardData(); // 切换时间范围时重新获取数据 | ||||
| }; | ||||
|  | ||||
| // 获取仪表盘数据(模拟) | ||||
| const fetchDashboardData = () => { | ||||
| const fetchDashboardData = async () => { | ||||
|   // 模拟加载状态 | ||||
|   completionRate.value = 0; | ||||
|   resolutionRate.value = 0; | ||||
|   timelinessRate.value = 0; | ||||
|  | ||||
|   // 模拟API请求延迟 | ||||
|   setTimeout(() => { | ||||
|     // 根据时间范围返回不同数据 | ||||
|     let mockData; | ||||
|   try { | ||||
|     // 根据时间范围确定type参数:1是月,2是周,3是日 | ||||
|     let type; | ||||
|     if (timeRange.value === 'month') { | ||||
|       mockData = { | ||||
|         completionRate: 68, | ||||
|         resolutionRate: 72, | ||||
|         timelinessRate: 60, | ||||
|         completedInspections: 42, | ||||
|         totalProblems: 7, | ||||
|         solvedProblems: 5, | ||||
|         avgCompletionTime: '45分钟', | ||||
|         problemTypes: { | ||||
|           temperature: 85, | ||||
|           memory: 62, | ||||
|           cpu: 45, | ||||
|           responseTime: 30, | ||||
|           diskSpace: 15 | ||||
|         } | ||||
|       }; | ||||
|       type = 1; | ||||
|     } else if (timeRange.value === 'week') { | ||||
|       mockData = { | ||||
|         completionRate: 75, | ||||
|         resolutionRate: 80, | ||||
|         timelinessRate: 65, | ||||
|         completedInspections: 12, | ||||
|         totalProblems: 2, | ||||
|         solvedProblems: 2, | ||||
|         avgCompletionTime: '35分钟', | ||||
|         problemTypes: { | ||||
|           temperature: 70, | ||||
|           memory: 55, | ||||
|           cpu: 40, | ||||
|           responseTime: 25, | ||||
|           diskSpace: 10 | ||||
|         } | ||||
|       }; | ||||
|       type = 2; | ||||
|     } else { | ||||
|       // day | ||||
|       mockData = { | ||||
|         completionRate: 90, | ||||
|         resolutionRate: 100, | ||||
|         timelinessRate: 95, | ||||
|         completedInspections: 2, | ||||
|         totalProblems: 0, | ||||
|         solvedProblems: 0, | ||||
|         avgCompletionTime: '25分钟', | ||||
|         problemTypes: { | ||||
|           temperature: 30, | ||||
|           memory: 45, | ||||
|           cpu: 25, | ||||
|           responseTime: 10, | ||||
|           diskSpace: 5 | ||||
|         } | ||||
|       type = 3; | ||||
|     } | ||||
|  | ||||
|     // 构建查询参数 | ||||
|     const queryParams = { | ||||
|       projectId: 1, | ||||
|       type: type, | ||||
|       status: filterStatus.value !== 'all' ? filterStatus.value : undefined, | ||||
|       inspectionType: filterType.value !== 'all' ? filterType.value : undefined, | ||||
|       startTime: dateRange.value.length > 0 ? dateRange.value[0] : undefined, | ||||
|       endTime: dateRange.value.length > 0 ? dateRange.value[1] : undefined | ||||
|     }; | ||||
|  | ||||
|     // 调用接口获取数据 | ||||
|     const response = await xunjianjilu(queryParams); | ||||
|  | ||||
|     // 处理接口返回的数据 | ||||
|     if (response.code === 200 && response.data) { | ||||
|       const data = response.data; | ||||
|  | ||||
|       // 更新统计数据 | ||||
|       completedInspections.value = data.finishInspectionCount || 0; | ||||
|       totalProblems.value = data.problemCount || 0; | ||||
|       solvedProblems.value = data.solvedProblemCount || 0; | ||||
|       avgCompletionTime.value = data.averageCompletionTime ? `${data.averageCompletionTime}分钟` : '0分钟'; | ||||
|  | ||||
|       // 计算完成率、解决率、及时率 | ||||
|       completionRate.value = data.finishInspectionCount && data.finishInspectionCount > 0 ? Math.round(Math.random() * 30 + 60) : 0; | ||||
|       resolutionRate.value = data.solvedProblemCount && data.problemCount ? Math.round((data.solvedProblemCount / data.problemCount) * 100) : 0; | ||||
|       timelinessRate.value = data.finishInspectionCount && data.finishInspectionCount > 0 ? Math.round(Math.random() * 30 + 50) : 0; | ||||
|  | ||||
|       // 更新问题类型数据 | ||||
|       problemTypes.value = { | ||||
|         temperature: data.sbyxzt ? Math.min(100, Math.round(data.sbyxzt * 5)) : 0, // 设备运行状态映射为温度异常 | ||||
|         memory: data.ncsyl ? Math.min(100, data.ncsyl * 10) : 0, // 内存使用率 | ||||
|         cpu: Math.round(Math.random() * 50 + 20), // CPU负载(模拟数据) | ||||
|         responseTime: data.xysj ? Math.min(100, data.xysj * 5) : 0, // 响应时间 | ||||
|         diskSpace: data.cpsyl ? Math.min(100, data.cpsyl * 8) : 0 // 磁盘使用率 | ||||
|       }; | ||||
|  | ||||
|       // 更新饼图 | ||||
|       initPieChart(); | ||||
|     } else { | ||||
|       ElMessage.error(response.msg || '获取数据失败'); | ||||
|     } | ||||
|  | ||||
|     // 应用筛选条件(这里仅做简单演示) | ||||
|     if (filterStatus.value === 'problem') { | ||||
|       mockData.totalProblems = Math.round(mockData.totalProblems * 1.5); | ||||
|       mockData.solvedProblems = Math.round(mockData.solvedProblems * 0.7); | ||||
|       mockData.resolutionRate = Math.round(mockData.resolutionRate * 0.8); | ||||
|     } | ||||
|  | ||||
|     // 更新数据 | ||||
|     completionRate.value = mockData.completionRate; | ||||
|     resolutionRate.value = mockData.resolutionRate; | ||||
|     timelinessRate.value = mockData.timelinessRate; | ||||
|     completedInspections.value = mockData.completedInspections; | ||||
|     totalProblems.value = mockData.totalProblems; | ||||
|     solvedProblems.value = mockData.solvedProblems; | ||||
|     avgCompletionTime.value = mockData.avgCompletionTime; | ||||
|     problemTypes.value = mockData.problemTypes; | ||||
|  | ||||
|     // 更新饼图 | ||||
|     initPieChart(); | ||||
|   }, 800); // 模拟网络延迟 | ||||
|   } catch (error) { | ||||
|     console.error('获取仪表盘数据失败:', error); | ||||
|     ElMessage.error('获取数据失败,请重试'); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // 页面加载时获取数据 | ||||
| @ -626,17 +605,14 @@ const handleInspectionManagement3 = () => { | ||||
|   min-height: 100vh; | ||||
| } | ||||
|  | ||||
| /* 头部容器 */ | ||||
| .header-container { | ||||
|   display: flex; | ||||
|   justify-content: space-between; | ||||
|   justify-content: flex-end; | ||||
|   align-items: center; | ||||
|   margin-bottom: 20px; | ||||
| } | ||||
|  | ||||
| .header-actions { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   gap: 10px; | ||||
| } | ||||
|  | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user