Merge branch 'dhr' of http://xny.yj-3d.com:3000/taoge_xiaodi/maintenance_system into tcy
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/attendanceperson.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 9.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/baoxiu.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/baoxiushijian.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/baoxiuwancheng.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/car.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 469 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/gongdan.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/gongzuo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 598 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/jingao.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 398 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/lixian.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 737 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/paidan.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/qiangxiu.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/qiangxiushijian.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/qiangxiuwancheng.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/renwu.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 944 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/renyuan.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 644 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/shanchu.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 498 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/shijian.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/tongguo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 431 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/wancheng.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/weibaoxiu.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/weiqiangxiu.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/xiugai.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 498 B | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/zaixian.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 800 B | 
							
								
								
									
										771
									
								
								src/views/zhinengxunjian/InspectionManagement.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,771 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="operation-inspection"> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |       <TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡和按钮组合 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">巡检计划</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">巡检任务</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement3">巡检记录</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |       <!-- 筛选栏 --> | ||||||
|  |       <div class="filter-bar"> | ||||||
|  |         <div class="filter-item"> | ||||||
|  |           <el-select v-model="planType" placeholder="计划类型" clearable> | ||||||
|  |             <el-option label="全部类型" value="all"></el-option> | ||||||
|  |             <el-option label="每日巡检" value="daily"></el-option> | ||||||
|  |             <el-option label="每周巡检" value="weekly"></el-option> | ||||||
|  |             <el-option label="每月巡检" value="monthly"></el-option> | ||||||
|  |             <el-option label="每季度巡检" value="quarterly"></el-option> | ||||||
|  |           </el-select> | ||||||
|  |         </div> | ||||||
|  |         <div class="filter-item"> | ||||||
|  |           <el-select v-model="status" placeholder="全部状态" clearable> | ||||||
|  |             <el-option label="全部状态" value="all"></el-option> | ||||||
|  |             <el-option label="启用中" value="enabled"></el-option> | ||||||
|  |             <el-option label="已停用" value="disabled"></el-option> | ||||||
|  |           </el-select> | ||||||
|  |         </div> | ||||||
|  |         <div class="filter-item"> | ||||||
|  |           <el-select v-model="inspectionObject" placeholder="巡检对象" clearable> | ||||||
|  |             <el-option label="全部对象" value="all"></el-option> | ||||||
|  |             <el-option label="服务器" value="server"></el-option> | ||||||
|  |             <el-option label="网络设备" value="network"></el-option> | ||||||
|  |             <el-option label="应用系统" value="application"></el-option> | ||||||
|  |             <el-option label="基础设施" value="infrastructure"></el-option> | ||||||
|  |           </el-select> | ||||||
|  |         </div> | ||||||
|  |         <div class="filter-actions"> | ||||||
|  |           <el-button type="primary" class="search-btn">搜索</el-button> | ||||||
|  |           <el-button type="primary" icon="el-icon-plus" class="create-btn" @click="handleCreate">手动创建计划</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |       <!-- 表格 --> | ||||||
|  |       <div class="table-wrapper"> | ||||||
|  |         <el-table :data="pagedTableData" stripe style="width: 100%" highlight-current-row class="custom-table"> | ||||||
|  |           <el-table-column align="center" prop="name" label="计划名称" style="width: 14.2%"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="type" label="类型" style="width: 14.2%"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="object" label="巡检对象" style="width: 14.2%"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="frequency" label="频率" style="width: 14.2%"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="status" label="状态" style="width: 14.2%"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-tag :type="scope.row.status === 'enabled' ? 'success' : 'info'" class="status-tag"> | ||||||
|  |                 {{ scope.row.status === 'enabled' ? '启用中' : '已停用' }} | ||||||
|  |               </el-tag> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |           <el-table-column align="center" prop="responsible" label="负责人" style="width: 14.2%"></el-table-column> | ||||||
|  |           <el-table-column align="center" label="操作" style="width: 14.2%" fixed="right"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-button type="text" @click="handleEdit(scope.row)" class="action-btn">编辑</el-button> | ||||||
|  |               <el-button type="text" @click="handleDetail(scope.row)" class="action-btn">详情</el-button> | ||||||
|  |               <el-button | ||||||
|  |                 type="text" | ||||||
|  |                 :disabled="scope.row.status === 'disabled'" | ||||||
|  |                 @click="handleEnable(scope.row)" | ||||||
|  |                 class="action-btn" | ||||||
|  |                 :class="{ 'text-success': scope.row.status === 'disabled' }" | ||||||
|  |               > | ||||||
|  |                 {{ scope.row.status === 'enabled' ? '停用' : '启用' }} | ||||||
|  |               </el-button> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |         </el-table> | ||||||
|  |       </div> | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-info"> | ||||||
|  |           显示第{{ (currentPage - 1) * pageSize + 1 }}到{{ Math.min(currentPage * pageSize, total) }}条,共有{{ total }}条记录 | ||||||
|  |         </div> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[10, 20, 30, 40]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="total, sizes, prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- 创建计划弹窗 --> | ||||||
|  |     <el-dialog v-model="dialogVisible" title="新建巡检计划" width="700px" class="create-plan-dialog" center :show-close="true"> | ||||||
|  |       <el-form :model="createForm" :rules="createFormRules" ref="createFormRef" label-width="150px" class="custom-form"> | ||||||
|  |         <el-form-item label="计划名称*" prop="planName" class="form-item-large"> | ||||||
|  |           <el-input v-model="createForm.planName" placeholder="请输入计划名称" class="custom-input" /> | ||||||
|  |         </el-form-item> | ||||||
|  |  | ||||||
|  |         <div class="form-row"> | ||||||
|  |           <el-form-item label="计划类型*" prop="planType" class="form-item-half"> | ||||||
|  |             <el-select v-model="createForm.planType" placeholder="请选择计划类型" class="custom-select"> | ||||||
|  |               <el-option label="每日巡检" value="daily" /> | ||||||
|  |               <el-option label="每周巡检" value="weekly" /> | ||||||
|  |               <el-option label="每月巡检" value="monthly" /> | ||||||
|  |               <el-option label="每季度巡检" value="quarterly" /> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="巡检对象类型*" prop="objectType" class="form-item-half"> | ||||||
|  |             <el-select v-model="createForm.objectType" placeholder="请选择对象类型" class="custom-select"> | ||||||
|  |               <el-option label="服务器" value="server" /> | ||||||
|  |               <el-option label="网络设备" value="network" /> | ||||||
|  |               <el-option label="应用系统" value="application" /> | ||||||
|  |               <el-option label="基础设施" value="infrastructure" /> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="form-row"> | ||||||
|  |           <el-form-item label="开始日期*" prop="startDate" class="form-item-half"> | ||||||
|  |             <el-date-picker | ||||||
|  |               v-model="createForm.startDate" | ||||||
|  |               type="date" | ||||||
|  |               placeholder="选择日期" | ||||||
|  |               format="YYYY-MM-DD" | ||||||
|  |               value-format="YYYY-MM-DD" | ||||||
|  |               class="custom-date-picker" | ||||||
|  |             /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="结束日期*" prop="endDate" class="form-item-half"> | ||||||
|  |             <el-date-picker | ||||||
|  |               v-model="createForm.endDate" | ||||||
|  |               type="date" | ||||||
|  |               placeholder="选择日期" | ||||||
|  |               format="YYYY-MM-DD" | ||||||
|  |               value-format="YYYY-MM-DD" | ||||||
|  |               class="custom-date-picker" | ||||||
|  |             /> | ||||||
|  |           </el-form-item> | ||||||
|  |         </div> | ||||||
|  |         <el-form-item label="巡检频率*" class="form-item-large"> | ||||||
|  |           <div style="display: flex; align-items: center; gap: 20px"> | ||||||
|  |             <el-radio-group v-model="createForm.frequencyType" class="frequency-radio-group"> | ||||||
|  |               <el-radio label="daily">每天</el-radio> | ||||||
|  |               <el-radio label="weekly">每周</el-radio> | ||||||
|  |               <el-radio label="monthly">每月</el-radio> | ||||||
|  |             </el-radio-group> | ||||||
|  |  | ||||||
|  |             <!-- 每周选择框 - 变小并排在单选框后面 --> | ||||||
|  |             <el-select | ||||||
|  |               v-if="createForm.frequencyType === 'weekly'" | ||||||
|  |               v-model="createForm.weekday" | ||||||
|  |               placeholder="选择周几" | ||||||
|  |               class="custom-select-small" | ||||||
|  |               style="width: 100px" | ||||||
|  |             > | ||||||
|  |               <el-option label="周一" value="1" /> | ||||||
|  |               <el-option label="周二" value="2" /> | ||||||
|  |               <el-option label="周三" value="3" /> | ||||||
|  |               <el-option label="周四" value="4" /> | ||||||
|  |               <el-option label="周五" value="5" /> | ||||||
|  |               <el-option label="周六" value="6" /> | ||||||
|  |               <el-option label="周日" value="0" /> | ||||||
|  |             </el-select> | ||||||
|  |  | ||||||
|  |             <!-- 每月选择框 - 变小并排在单选框后面 --> | ||||||
|  |             <el-select | ||||||
|  |               v-if="createForm.frequencyType === 'monthly'" | ||||||
|  |               v-model="createForm.monthday" | ||||||
|  |               placeholder="选择几号" | ||||||
|  |               class="custom-select-small" | ||||||
|  |               style="width: 100px" | ||||||
|  |             > | ||||||
|  |               <template v-for="day in 31" :key="day"> | ||||||
|  |                 <el-option :label="day + '号'" :value="day" /> | ||||||
|  |               </template> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |         </el-form-item> | ||||||
|  |  | ||||||
|  |         <div class="form-row" s> | ||||||
|  |           <el-form-item label="计划开始时间*" prop="startTime" class="form-item-half"> | ||||||
|  |             <el-time-picker v-model="createForm.startTime" placeholder="选择时间" format="HH:mm" value-format="HH:mm" class="custom-time-picker" /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="预计时长(分钟)" class="form-item-half"> | ||||||
|  |             <el-input v-model.number="createForm.estimatedDuration" class="custom-input" /> | ||||||
|  |           </el-form-item> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <el-form-item label="负责人*" prop="responsiblePerson" class="form-item-large"> | ||||||
|  |           <el-select v-model="createForm.responsiblePerson" placeholder="请选择负责人" class="custom-select"> | ||||||
|  |             <el-option label="张明" value="zhangming" /> | ||||||
|  |             <el-option label="李华" value="lihua" /> | ||||||
|  |             <el-option label="王强" value="wangqiang" /> | ||||||
|  |           </el-select> | ||||||
|  |         </el-form-item> | ||||||
|  |  | ||||||
|  |         <el-form-item label="巡检项*" class="form-item-large"> | ||||||
|  |           <el-checkbox-group v-model="createForm.inspectionItems" style="border: 0.1 solid black; padding: 5px"> | ||||||
|  |             <el-checkbox label="CPU使用率检查" /> | ||||||
|  |             <el-checkbox label="内存使用情况" /> | ||||||
|  |             <el-checkbox label="磁盘空间检查" /> | ||||||
|  |             <el-checkbox label="网络连接状态" /> | ||||||
|  |             <el-checkbox label="系统日志检查" /> | ||||||
|  |           </el-checkbox-group> | ||||||
|  |         </el-form-item> | ||||||
|  |  | ||||||
|  |         <el-form-item label="备注说明" prop="remarks" class="form-item-large"> | ||||||
|  |           <el-input v-model="createForm.remarks" type="textarea" placeholder="请输入备注" rows="3" class="custom-textarea" /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-form> | ||||||
|  |  | ||||||
|  |       <template #footer> | ||||||
|  |         <span class="dialog-footer"> | ||||||
|  |           <el-button @click="cancelCreatePlan">取消</el-button> | ||||||
|  |           <el-button type="primary" @click="submitCreatePlan">新增任务</el-button> | ||||||
|  |         </span> | ||||||
|  |       </template> | ||||||
|  |     </el-dialog> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | // 表单引用 | ||||||
|  | const createFormRef = ref(null); | ||||||
|  | import { ref, computed, reactive } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 激活的选项卡 | ||||||
|  | const activeTab = ref('plan'); | ||||||
|  | // 计划类型 | ||||||
|  | const planType = ref('all'); | ||||||
|  | // 状态 | ||||||
|  | const status = ref('all'); | ||||||
|  | // 巡检对象 | ||||||
|  | const inspectionObject = ref('all'); | ||||||
|  | // 原始表格数据 | ||||||
|  | const rawTableData = ref([ | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '网络设备安全巡检 2025-04-15', | ||||||
|  |     type: '每周巡检', | ||||||
|  |     object: '网络设备', | ||||||
|  |     frequency: '每天10:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '数据库性能巡检 2025-03-03', | ||||||
|  |     type: '每月巡检', | ||||||
|  |     object: '应用系统', | ||||||
|  |     frequency: '每月1日14:00', | ||||||
|  |     status: 'disabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '机房环境季度检查', | ||||||
|  |     type: '每季度巡检', | ||||||
|  |     object: '基础设备', | ||||||
|  |     frequency: '每季度第一个月5号', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '生产服务器每日巡检 2025-05-14', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '服务器', | ||||||
|  |     frequency: '每天8:30', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '张明' | ||||||
|  |   }, | ||||||
|  |   // 增加更多数据用于测试分页 | ||||||
|  |   { | ||||||
|  |     name: '应用系统安全检查', | ||||||
|  |     type: '每周巡检', | ||||||
|  |     object: '应用系统', | ||||||
|  |     frequency: '每周五16:00', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '李华' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: '网络带宽监控', | ||||||
|  |     type: '每日巡检', | ||||||
|  |     object: '网络设备', | ||||||
|  |     frequency: '每天12:00', | ||||||
|  |     status: 'enabled', | ||||||
|  |     responsible: '王强' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  | // 当前页码 | ||||||
|  | const currentPage = ref(1); | ||||||
|  | // 每页条数 - 与分页控件默认值保持一致 | ||||||
|  | const pageSize = ref(10); | ||||||
|  | // 总条数 - 从原始数据计算得出 | ||||||
|  | const total = ref(rawTableData.value.length); | ||||||
|  |  | ||||||
|  | // 计算属性:根据当前页码和每页条数获取分页后的数据 | ||||||
|  | const pagedTableData = computed(() => { | ||||||
|  |   const startIndex = (currentPage.value - 1) * pageSize.value; | ||||||
|  |   const endIndex = startIndex + pageSize.value; | ||||||
|  |   return rawTableData.value.slice(startIndex, endIndex); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 每页条数改变 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 当前页码改变 | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 编辑 | ||||||
|  | const handleEdit = (row) => { | ||||||
|  |   console.log('编辑', row); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 详情 | ||||||
|  | const handleDetail = (row) => { | ||||||
|  |   console.log('详情', row); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 启用/停用 | ||||||
|  | const handleEnable = (row) => { | ||||||
|  |   row.status = row.status === 'enabled' ? 'disabled' : 'enabled'; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 选项卡切换 | ||||||
|  | const handleTabChange = (newTab, oldTab) => { | ||||||
|  |   // 可以在这里添加选项卡切换时的逻辑 | ||||||
|  |   console.log('选项卡切换:', newTab, oldTab); | ||||||
|  |   return true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建计划弹窗相关 | ||||||
|  | const dialogVisible = ref(false); | ||||||
|  | const createForm = reactive({ | ||||||
|  |   planName: '', | ||||||
|  |   planType: '', | ||||||
|  |   objectType: '', | ||||||
|  |   startDate: '', | ||||||
|  |   endDate: '', | ||||||
|  |   frequencyType: 'daily', | ||||||
|  |   frequencyValue: '', | ||||||
|  |   weekday: '', // 存储周几 | ||||||
|  |   monthday: '', // 存储几号 | ||||||
|  |   startTime: '', | ||||||
|  |   estimatedDuration: 60, | ||||||
|  |   responsiblePerson: '', | ||||||
|  |   inspectionItems: [], | ||||||
|  |   remarks: '' | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 创建计划表单验证规则 | ||||||
|  | const createFormRules = computed(() => ({ | ||||||
|  |   planName: [{ required: true, message: '请输入计划名称', trigger: 'blur' }], | ||||||
|  |   planType: [{ required: true, message: '请选择计划类型', trigger: 'change' }], | ||||||
|  |   objectType: [{ required: true, message: '请选择对象类型', trigger: 'change' }], | ||||||
|  |   startDate: [{ required: true, message: '请选择开始日期', trigger: 'change' }], | ||||||
|  |   endDate: [{ required: true, message: '请选择结束日期', trigger: 'change' }], | ||||||
|  |   startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }], | ||||||
|  |   responsiblePerson: [{ required: true, message: '请选择负责人', trigger: 'change' }], | ||||||
|  |   weekday: createForm.frequencyType === 'weekly' ? [{ required: true, message: '请选择周几', trigger: 'change' }] : [], | ||||||
|  |   monthday: createForm.frequencyType === 'monthly' ? [{ required: true, message: '请选择几号', trigger: 'change' }] : [] | ||||||
|  | })); | ||||||
|  |  | ||||||
|  | // 打开创建计划弹窗 | ||||||
|  | const handleCreate = () => { | ||||||
|  |   dialogVisible.value = true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 提交创建计划 | ||||||
|  | const submitCreatePlan = () => { | ||||||
|  |   console.log('提交创建计划:', createForm); | ||||||
|  |   // 这里可以添加实际的创建计划逻辑 | ||||||
|  |   dialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   Object.keys(createForm).forEach((key) => { | ||||||
|  |     if (Array.isArray(createForm[key])) { | ||||||
|  |       createForm[key] = []; | ||||||
|  |     } else if (key === 'estimatedDuration') { | ||||||
|  |       createForm[key] = 60; | ||||||
|  |     } else if (key === 'frequencyType') { | ||||||
|  |       createForm[key] = 'daily'; | ||||||
|  |     } else { | ||||||
|  |       createForm[key] = ''; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 取消创建计划 | ||||||
|  | const cancelCreatePlan = () => { | ||||||
|  |   dialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   Object.keys(createForm).forEach((key) => { | ||||||
|  |     if (Array.isArray(createForm[key])) { | ||||||
|  |       createForm[key] = []; | ||||||
|  |     } else if (key === 'estimatedDuration') { | ||||||
|  |       createForm[key] = 60; | ||||||
|  |     } else if (key === 'frequencyType') { | ||||||
|  |       createForm[key] = 'daily'; | ||||||
|  |     } else { | ||||||
|  |       createForm[key] = ''; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/xunjianrenwu'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/xunjianjihua'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | /* 样式保持不变 */ | ||||||
|  | .operation-inspection { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 标题区域样式 */ | ||||||
|  | .title-section { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .page-title { | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0 0 8px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .page-subtitle { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #909399; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs { | ||||||
|  |   border-bottom: none; | ||||||
|  |   padding-top: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__header { | ||||||
|  |   margin: 0 -20px 0 -20px; | ||||||
|  |   padding: 0 20px; | ||||||
|  |   border-bottom: 1px solid #e4e7ed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__nav-wrap::after { | ||||||
|  |   height: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   padding: 12px 20px; | ||||||
|  |   margin-right: 20px; | ||||||
|  |   border-bottom: 2px solid transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item.is-active { | ||||||
|  |   color: #409eff; | ||||||
|  |   border-bottom-color: #409eff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item:hover { | ||||||
|  |   color: #409eff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select { | ||||||
|  |   width: 150px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-btn, | ||||||
|  | .create-btn { | ||||||
|  |   height: 36px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 表格样式 */ | ||||||
|  | .table-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table { | ||||||
|  |   border: 1px solid #ebeef5; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table th { | ||||||
|  |   background-color: #fafafa; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #606266; | ||||||
|  |   text-align: left; | ||||||
|  |   padding: 12px 16px; | ||||||
|  |   border-bottom: 1px solid #ebeef5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table td { | ||||||
|  |   padding: 12px 16px; | ||||||
|  |   border-bottom: 1px solid #ebeef5; | ||||||
|  |   color: #303133; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table tr:hover { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table tr.current-row { | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag { | ||||||
|  |   padding: 4px 8px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn { | ||||||
|  |   color: #409eff; | ||||||
|  |   font-size: 12px; | ||||||
|  |   padding: 4px 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn:hover { | ||||||
|  |   color: #66b1ff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .pagination-section { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 16px 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-info { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination { | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination__sizes { | ||||||
|  |   margin-right: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination button { | ||||||
|  |   min-width: 32px; | ||||||
|  |   height: 32px; | ||||||
|  |   line-height: 32px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination .el-pager li { | ||||||
|  |   min-width: 32px; | ||||||
|  |   height: 32px; | ||||||
|  |   line-height: 32px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination .el-pager li.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  | } | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   cursor: pointer; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .filter-bar { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-actions { | ||||||
|  |     margin-left: 0; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										31
									
								
								src/views/zhinengxunjian/TitleComponent.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,31 @@ | |||||||
|  | <template> | ||||||
|  |   <el-row style="padding: 0 20px"> | ||||||
|  |     <el-col> | ||||||
|  |       <div | ||||||
|  |         style="color: rgba(0, 30, 59, 1); font-family: 'Alibaba-PuHuiTi-Bold'; margin: 10px 0 0 0" | ||||||
|  |         :style="{ fontSize: fontLevelMap[props.fontLevel] }" | ||||||
|  |       > | ||||||
|  |         {{ props.title }} | ||||||
|  |       </div> | ||||||
|  |     </el-col> | ||||||
|  |     <el-col> | ||||||
|  |       <p style="color: rgba(154, 154, 154, 1); font-size: 14px"> | ||||||
|  |         {{ props.subtitle }} | ||||||
|  |       </p> | ||||||
|  |     </el-col> | ||||||
|  |   </el-row> | ||||||
|  | </template> | ||||||
|  | <script setup> | ||||||
|  | const props = defineProps({ | ||||||
|  |   title: String, | ||||||
|  |   subtitle: String, | ||||||
|  |   fontLevel: { | ||||||
|  |     type: Number, | ||||||
|  |     default: 1 | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | const fontLevelMap = { | ||||||
|  |   1: '24px', | ||||||
|  |   2: '18px' | ||||||
|  | }; | ||||||
|  | </script> | ||||||
							
								
								
									
										1137
									
								
								src/views/zhinengxunjian/banzhuzhuangtai.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1147
									
								
								src/views/zhinengxunjian/baoxiuguanli.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										714
									
								
								src/views/zhinengxunjian/baoxiujilu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,714 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="inspection-tasks"> | ||||||
|  |       <!-- 导航栏 --> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 页面标题 --> | ||||||
|  |       <TitleComponent title="报修管理模块" subtitle="创建报修任务,跟进报修记录,管理维修进度"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">报修任务</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">报修记录</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 筛选栏 --> | ||||||
|  |       <div class="filter-bar"> | ||||||
|  |         <div class="filter-container"> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="taskStatus" placeholder="任务状态"> | ||||||
|  |               <el-option label="待执行" value="pending"></el-option> | ||||||
|  |               <el-option label="处理中" value="processing"></el-option> | ||||||
|  |               <el-option label="已完成" value="completed"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="priority" placeholder="优先级"> | ||||||
|  |               <el-option label="高优先级" value="high"></el-option> | ||||||
|  |               <el-option label="中优先级" value="medium"></el-option> | ||||||
|  |               <el-option label="低优先级" value="low"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="executor" placeholder="处理人员"> | ||||||
|  |               <el-option label="全部人员" value="all"></el-option> | ||||||
|  |               <el-option label="李阳" value="liyang"></el-option> | ||||||
|  |               <el-option label="张明" value="zhangming"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-date-picker | ||||||
|  |               v-model="dateRange" | ||||||
|  |               type="datetimerange" | ||||||
|  |               start-placeholder="开始时间" | ||||||
|  |               end-placeholder="结束时间" | ||||||
|  |               format="YYYY-MM-DD HH:mm" | ||||||
|  |               value-format="YYYY-MM-DD HH:mm" | ||||||
|  |             /> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-actions"> | ||||||
|  |             <el-button type="primary" class="search-btn" @click="handleSearch"> 搜索 </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 统计卡片区域 --> | ||||||
|  |       <div class="statistics-container"> | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">本月报修数</p> | ||||||
|  |             <p class="stat-value">24</p> | ||||||
|  |             <p class="stat-trend up">较上月 +4.2%</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon"> | ||||||
|  |             <img src="@/assets/images/baoxiu.png" alt="本月报修数" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">平均处理时长</p> | ||||||
|  |             <p class="stat-value">3.5小时</p> | ||||||
|  |             <p class="stat-trend down">较上月 -0.6小时</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon"> | ||||||
|  |             <img src="@/assets/images/baoxiushijian.png" alt="平均处理时长" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">待处理报修</p> | ||||||
|  |             <p class="stat-value">15</p> | ||||||
|  |             <p class="stat-trend warning">需及时处理</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon warning"> | ||||||
|  |             <img src="@/assets/images/weibaoxiu.png" alt="待处理报修" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">完成率</p> | ||||||
|  |             <p class="stat-value">92%</p> | ||||||
|  |             <p class="stat-trend up">较上月 +2.1%</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon success"> | ||||||
|  |             <img src="@/assets/images/baoxiuwancheng.png" alt="完成率" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 报修记录表格 --> | ||||||
|  |       <div class="table-container"> | ||||||
|  |         <el-table :data="filteredRecords" border style="width: 100%" class="record-table"> | ||||||
|  |           <el-table-column align="center" prop="reportNo" label="报修单号" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="content" label="报修内容" min-width="200"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="reporter" label="报修人" min-width="90"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="reportTime" label="报修时间" min-width="150"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="handler" label="处理人员" min-width="90"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="status" label="处理状态" min-width="90"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <span :class="`status-tag ${scope.row.statusClass}`">{{ scope.row.status }}</span> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |           <el-table-column align="center" prop="handleTime" label="处理时间" min-width="150"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="result" label="维修结果" min-width="180"></el-table-column> | ||||||
|  |           <el-table-column align="center" label="操作" min-width="140"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-button type="text" class="detail-btn" @click="handleDetail(scope.row)"> 详情 </el-button> | ||||||
|  |               <el-button type="text" :class="scope.row.actionClass" @click="handleAction(scope.row)"> | ||||||
|  |                 {{ scope.row.actionText }} | ||||||
|  |               </el-button> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |         </el-table> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[7, 15, 20, 30]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const taskStatus = ref(''); | ||||||
|  | const priority = ref(''); | ||||||
|  | const executor = ref(''); | ||||||
|  | const dateRange = ref([]); | ||||||
|  |  | ||||||
|  | // 分页相关 | ||||||
|  | const currentPage = ref(3); | ||||||
|  | const pageSize = ref(7); | ||||||
|  |  | ||||||
|  | // 报修记录数据 | ||||||
|  | const repairRecords = ref([ | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-001', | ||||||
|  |     content: '服务器A1电源故障', | ||||||
|  |     reporter: '张明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李阳', | ||||||
|  |     status: '处理中', | ||||||
|  |     statusClass: 'processing', | ||||||
|  |     handleTime: '--', | ||||||
|  |     result: '--', | ||||||
|  |     actionText: '跟进', | ||||||
|  |     actionClass: 'follow-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-002', | ||||||
|  |     content: '测试软件授权过期', | ||||||
|  |     reporter: '张明', | ||||||
|  |     reportTime: '2025-06-20 09:15', | ||||||
|  |     handler: '李阳', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     handleTime: '2025-06-21 14:30', | ||||||
|  |     result: '已重新授权', | ||||||
|  |     actionText: '评价', | ||||||
|  |     actionClass: 'evaluate-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-003', | ||||||
|  |     content: '打印机卡纸故障', | ||||||
|  |     reporter: '张明', | ||||||
|  |     reportTime: '2025-06-20 10:45', | ||||||
|  |     handler: '李阳', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     handleTime: '2025-06-21 10:15', | ||||||
|  |     result: '已清除卡纸,设备正常', | ||||||
|  |     actionText: '评价', | ||||||
|  |     actionClass: 'evaluate-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-004', | ||||||
|  |     content: '网络交换机端口故障', | ||||||
|  |     reporter: '张明', | ||||||
|  |     reportTime: '2025-06-20 13:20', | ||||||
|  |     handler: '李阳', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     handleTime: '2025-06-20 15:40', | ||||||
|  |     result: '已更换端口', | ||||||
|  |     actionText: '评价', | ||||||
|  |     actionClass: 'evaluate-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-005', | ||||||
|  |     content: '服务器A1电源故障', | ||||||
|  |     reporter: '张明', | ||||||
|  |     reportTime: '2025-06-20 14:50', | ||||||
|  |     handler: '李阳', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     handleTime: '2025-06-21 09:30', | ||||||
|  |     result: '已重新授权', | ||||||
|  |     actionText: '评价', | ||||||
|  |     actionClass: 'evaluate-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-006', | ||||||
|  |     content: '机房空调温度异常', | ||||||
|  |     reporter: '张明', | ||||||
|  |     reportTime: '2025-06-20 16:10', | ||||||
|  |     handler: '李阳', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     handleTime: '2025-06-20 17:25', | ||||||
|  |     result: '已修复,温度正常', | ||||||
|  |     actionText: '评价', | ||||||
|  |     actionClass: 'evaluate-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-007', | ||||||
|  |     content: '监控系统无法连接', | ||||||
|  |     reporter: '张明', | ||||||
|  |     reportTime: '2025-06-20 18:05', | ||||||
|  |     handler: '李阳', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     handleTime: '2025-06-21 08:45', | ||||||
|  |     result: '网络配置已重置', | ||||||
|  |     actionText: '评价', | ||||||
|  |     actionClass: 'evaluate-btn' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 总记录数 | ||||||
|  | const total = ref(54); | ||||||
|  |  | ||||||
|  | // 筛选后的记录 | ||||||
|  | const filteredRecords = computed(() => { | ||||||
|  |   // 实际应用中这里会根据筛选条件过滤数据 | ||||||
|  |   return repairRecords.value; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 搜索处理 | ||||||
|  | const handleSearch = () => { | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  |   // 实际应用中这里会根据筛选条件过滤数据 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建任务弹窗相关 | ||||||
|  | const createTaskDialogVisible = ref(false); | ||||||
|  | const createTaskForm = ref({ | ||||||
|  |   taskName: '', | ||||||
|  |   repairContent: '', | ||||||
|  |   timeRange: [], | ||||||
|  |   priority: '', | ||||||
|  |   handler: '' | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | const createTaskRules = { | ||||||
|  |   taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }], | ||||||
|  |   repairContent: [{ required: true, message: '请输入报修内容', trigger: 'blur' }], | ||||||
|  |   timeRange: [{ required: true, message: '请选择时间范围', trigger: 'change' }] | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 保存任务 | ||||||
|  | const handleSaveTask = () => { | ||||||
|  |   // 模拟保存任务逻辑 | ||||||
|  |   console.log('保存任务:', createTaskForm.value); | ||||||
|  |   // 关闭弹窗 | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     taskName: '', | ||||||
|  |     repairContent: '', | ||||||
|  |     timeRange: [], | ||||||
|  |     priority: '', | ||||||
|  |     handler: '' | ||||||
|  |   }; | ||||||
|  |   // 这里可以添加成功提示和刷新任务列表的逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 取消创建任务 | ||||||
|  | const handleCancelCreateTask = () => { | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     taskName: '', | ||||||
|  |     repairContent: '', | ||||||
|  |     timeRange: [], | ||||||
|  |     priority: '', | ||||||
|  |     handler: '' | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页事件 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 查看详情 | ||||||
|  | const handleDetail = (record) => { | ||||||
|  |   console.log('查看详情:', record); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 处理操作 | ||||||
|  | const handleAction = (record) => { | ||||||
|  |   console.log('执行操作:', record.actionText, record); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导航事件 | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/baoxiujilu'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .inspection-tasks { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-container { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select, | ||||||
|  | .filter-bar .el-date-picker { | ||||||
|  |   width: 180px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select .el-input__inner, | ||||||
|  | .filter-bar .el-date-picker .el-input__inner { | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border-color: #dcdfe6; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select .el-input__inner:focus, | ||||||
|  | .filter-bar .el-date-picker .el-input__inner:focus { | ||||||
|  |   border-color: #165dff; | ||||||
|  |   box-shadow: 0 0 0 2px rgba(22, 93, 255, 0.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 12px; | ||||||
|  |   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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .create-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .create-btn:hover { | ||||||
|  |   background-color: #0e42d2; | ||||||
|  |   border-color: #0e42d2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计卡片样式 */ | ||||||
|  | .statistics-container { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); | ||||||
|  |   gap: 20px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-card { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 20px; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   transition: transform 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-card:hover { | ||||||
|  |   transform: translateY(-3px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-info { | ||||||
|  |   flex: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #86909c; | ||||||
|  |   margin: 0 0 8px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #1d2129; | ||||||
|  |   margin: 0 0 4px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend { | ||||||
|  |   font-size: 12px; | ||||||
|  |   margin: 0; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.up { | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.up::before { | ||||||
|  |   content: '↑'; | ||||||
|  |   margin-right: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.down { | ||||||
|  |   color: #ff4d4f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.down::before { | ||||||
|  |   content: '↓'; | ||||||
|  |   margin-right: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.warning { | ||||||
|  |   color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-icon { | ||||||
|  |   width: 55px; | ||||||
|  |   height: 55px; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-image { | ||||||
|  |   width: 45px; | ||||||
|  |   height: 45px; | ||||||
|  |   object-fit: contain; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 表格样式 */ | ||||||
|  | .table-container { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-table { | ||||||
|  |   border-collapse: separate; | ||||||
|  |   border-spacing: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-table th { | ||||||
|  |   background-color: #f7f8fa; | ||||||
|  |   color: #4e5969; | ||||||
|  |   font-weight: 500; | ||||||
|  |   font-size: 14px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-table td { | ||||||
|  |   color: #1d2129; | ||||||
|  |   font-size: 14px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag { | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.processing { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #faad14; | ||||||
|  |   border: 1px solid #fff1b8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.completed { | ||||||
|  |   background-color: #f0f9eb; | ||||||
|  |   color: #52c41a; | ||||||
|  |   border: 1px solid #e1f3d8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .follow-btn { | ||||||
|  |   color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .evaluate-btn { | ||||||
|  |   color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .pagination-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   margin-top: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination { | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination button, | ||||||
|  | .pagination-controls .el-pagination .el-pager li { | ||||||
|  |   min-width: 36px; | ||||||
|  |   height: 36px; | ||||||
|  |   line-height: 36px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination .el-pager li.active { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   color: #fff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   cursor: pointer; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .statistics-container { | ||||||
|  |     grid-template-columns: repeat(2, 1fr); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .inspection-tasks { | ||||||
|  |     padding: 16px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-actions { | ||||||
|  |     margin-left: 0; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-bar .el-select, | ||||||
|  |   .filter-bar .el-date-picker { | ||||||
|  |     width: 100%; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .statistics-container { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .table-container { | ||||||
|  |     overflow-x: auto; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										729
									
								
								src/views/zhinengxunjian/cheliangzhuangtai.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,729 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="execution-records"> | ||||||
|  |       <!-- 顶部导航栏 --> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 页面标题 --> | ||||||
|  |       <TitleComponent title="运维组织模块" subtitle="实时监控人员状态、车辆状态和班组状态"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">人员状态</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">车辆状态</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement3">班组状态</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 搜索和筛选区 --> | ||||||
|  |       <div class="search-filter"> | ||||||
|  |         <div class="search-container"> | ||||||
|  |           <!-- 左侧统计数据和车辆图片组合 --> | ||||||
|  |           <div class="stats-and-image"> | ||||||
|  |             <!-- 车辆统计区域 --> | ||||||
|  |             <div class="vehicle-stats"> | ||||||
|  |               <!-- 总车辆数 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-label">总车辆数</div> | ||||||
|  |                 <div class="stat-value">{{ totalVehicles }}</div> | ||||||
|  |                 <div class="stat-desc">所有运维车辆总数</div> | ||||||
|  |               </div> | ||||||
|  |               <!-- 可用车辆 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-label">可用车辆</div> | ||||||
|  |                 <div class="stat-value">{{ availableVehicles }}</div> | ||||||
|  |                 <div class="stat-desc available">可立即调度</div> | ||||||
|  |               </div> | ||||||
|  |               <!-- 使用中 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-label">使用中</div> | ||||||
|  |                 <div class="stat-value">{{ inUseVehicles }}</div> | ||||||
|  |                 <div class="stat-desc in-use">执行任务中</div> | ||||||
|  |               </div> | ||||||
|  |               <!-- 维修/保养 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-label">维修/保养</div> | ||||||
|  |                 <div class="stat-value">{{ maintenanceVehicles }}</div> | ||||||
|  |                 <div class="stat-desc maintenance">预计2天后可用</div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <!-- 车辆图片 --> | ||||||
|  |             <img src="@/assets/images/car.png" class="img-car" alt="车辆图片" /> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 右侧搜索区域 --> | ||||||
|  |           <div class="search-integrated"> | ||||||
|  |             <div class="search-box"> | ||||||
|  |               <div class="search-label">搜索车牌号</div> | ||||||
|  |               <div class="license-plate-input"> | ||||||
|  |                 <span class="plate-prefix">京</span> | ||||||
|  |                 <span class="plate-dot">·</span> | ||||||
|  |                 <el-input v-model="plateNumber1" maxlength="1" class="plate-char"></el-input> | ||||||
|  |                 <el-input v-model="plateNumber2" maxlength="1" class="plate-char"></el-input> | ||||||
|  |                 <el-input v-model="plateNumber3" maxlength="1" class="plate-char"></el-input> | ||||||
|  |                 <el-input v-model="plateNumber4" maxlength="1" class="plate-char"></el-input> | ||||||
|  |                 <el-input v-model="plateNumber5" maxlength="1" class="plate-char"></el-input> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 车辆列表表格 --> | ||||||
|  |       <div class="table-wrapper"> | ||||||
|  |         <el-table :data="pagedTableData" stripe style="width: 100%" highlight-current-row class="custom-table"> | ||||||
|  |           <el-table-column align="center" prop="vehicleId" label="车辆编号" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="licensePlate" label="车牌号" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="vehicleType" label="车辆类型" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="team" label="所属班组" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="responsiblePerson" label="负责人" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="currentTask" label="当前任务" min-width="150"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="status" label="当前状态" min-width="120"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-tag :type="getStatusTagType(scope.row.status)" class="status-tag"> | ||||||
|  |                 {{ scope.row.status }} | ||||||
|  |               </el-tag> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |           <el-table-column align="center" prop="nextMaintenance" label="下次保养" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" label="操作" min-width="180" fixed="right"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-button type="text" @click="handleViewDetails(scope.row)" size="small" class="action-btn">详情</el-button> | ||||||
|  |               <el-button | ||||||
|  |                 type="text" | ||||||
|  |                 @click="handleDispatch(scope.row)" | ||||||
|  |                 size="small" | ||||||
|  |                 class="action-btn dispatch-btn" | ||||||
|  |                 v-if="scope.row.status === '可用'" | ||||||
|  |               > | ||||||
|  |                 调度 | ||||||
|  |               </el-button> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |         </el-table> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-info"> | ||||||
|  |           显示第{{ (currentPage - 1) * pageSize + 1 }}到{{ Math.min(currentPage * pageSize, total) }}条,共{{ total }}条记录 | ||||||
|  |         </div> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[10, 20, 30, 40]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 搜索和筛选条件 | ||||||
|  | const searchKeyword = ref(''); | ||||||
|  | const plateNumber1 = ref(''); | ||||||
|  | const plateNumber2 = ref(''); | ||||||
|  | const plateNumber3 = ref(''); | ||||||
|  | const plateNumber4 = ref(''); | ||||||
|  | const plateNumber5 = ref(''); | ||||||
|  |  | ||||||
|  | // 车辆数据 | ||||||
|  | const rawTableData = ref([ | ||||||
|  |   { | ||||||
|  |     vehicleId: 'CAR-001', | ||||||
|  |     licensePlate: '京A·12345', | ||||||
|  |     vehicleType: '工具车', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     responsiblePerson: '赵工', | ||||||
|  |     currentTask: '无', | ||||||
|  |     status: '可用', | ||||||
|  |     nextMaintenance: '2023-07-15' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     vehicleId: 'CAR-003', | ||||||
|  |     licensePlate: '京B·67890', | ||||||
|  |     vehicleType: '小型货车', | ||||||
|  |     team: '第二运维组', | ||||||
|  |     responsiblePerson: '赵工', | ||||||
|  |     currentTask: 'WO-2023-0619-055', | ||||||
|  |     status: '使用中', | ||||||
|  |     nextMaintenance: '2023-08-20' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     vehicleId: 'CAR-005', | ||||||
|  |     licensePlate: '京C·24680', | ||||||
|  |     vehicleType: '工程车', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     responsiblePerson: '赵工', | ||||||
|  |     currentTask: 'WO-2023-0618-054', | ||||||
|  |     status: '使用中', | ||||||
|  |     nextMaintenance: '2023-07-15' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     vehicleId: 'CAR-007', | ||||||
|  |     licensePlate: '京D·13579', | ||||||
|  |     vehicleType: '面包车', | ||||||
|  |     team: '第三运维组', | ||||||
|  |     responsiblePerson: '赵工', | ||||||
|  |     currentTask: '无', | ||||||
|  |     status: '维修中', | ||||||
|  |     nextMaintenance: '2023-07-15' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     vehicleId: 'CAR-009', | ||||||
|  |     licensePlate: '京E·12345', | ||||||
|  |     vehicleType: '工具车', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     responsiblePerson: '赵工', | ||||||
|  |     currentTask: '无', | ||||||
|  |     status: '可用', | ||||||
|  |     nextMaintenance: '2023-07-15' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     vehicleId: 'CAR-011', | ||||||
|  |     licensePlate: '京F·12345', | ||||||
|  |     vehicleType: '工具车', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     responsiblePerson: '赵工', | ||||||
|  |     currentTask: '无', | ||||||
|  |     status: '可用', | ||||||
|  |     nextMaintenance: '2023-07-15' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     vehicleId: 'CAR-013', | ||||||
|  |     licensePlate: '京G·12345', | ||||||
|  |     vehicleType: '工具车', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     responsiblePerson: '赵工', | ||||||
|  |     currentTask: '无', | ||||||
|  |     status: '可用', | ||||||
|  |     nextMaintenance: '2023-07-15' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 分页相关 | ||||||
|  | const currentPage = ref(1); | ||||||
|  | const pageSize = ref(10); | ||||||
|  | const total = ref(rawTableData.value.length); | ||||||
|  |  | ||||||
|  | // 统计数据 | ||||||
|  | const totalVehicles = computed(() => rawTableData.value.length); | ||||||
|  | const availableVehicles = computed(() => rawTableData.value.filter((v) => v.status === '可用').length); | ||||||
|  | const inUseVehicles = computed(() => rawTableData.value.filter((v) => v.status === '使用中').length); | ||||||
|  | const maintenanceVehicles = computed(() => rawTableData.value.filter((v) => v.status === '维修中').length); | ||||||
|  |  | ||||||
|  | // 分页处理后的数据 | ||||||
|  | const pagedTableData = computed(() => { | ||||||
|  |   // 筛选逻辑 | ||||||
|  |   let filteredData = [...rawTableData.value]; | ||||||
|  |  | ||||||
|  |   // 搜索关键词筛选 | ||||||
|  |   if (searchKeyword.value) { | ||||||
|  |     const keyword = searchKeyword.value.toLowerCase(); | ||||||
|  |     filteredData = filteredData.filter( | ||||||
|  |       (item) => | ||||||
|  |         item.vehicleId.toLowerCase().includes(keyword) || | ||||||
|  |         item.licensePlate.toLowerCase().includes(keyword) || | ||||||
|  |         item.vehicleType.toLowerCase().includes(keyword) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // 车牌号筛选 | ||||||
|  |   const plateNumber = plateNumber1.value + plateNumber2.value + plateNumber3.value + plateNumber4.value + plateNumber5.value; | ||||||
|  |   if (plateNumber) { | ||||||
|  |     filteredData = filteredData.filter((item) => item.licensePlate.replace(/[·\s]/g, '').includes(plateNumber)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // 更新总条数 | ||||||
|  |   total.value = filteredData.length; | ||||||
|  |  | ||||||
|  |   // 分页处理 | ||||||
|  |   const startIndex = (currentPage.value - 1) * pageSize.value; | ||||||
|  |   const endIndex = startIndex + pageSize.value; | ||||||
|  |   return filteredData.slice(startIndex, endIndex); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 获取状态标签样式 | ||||||
|  | const getStatusTagType = (status) => { | ||||||
|  |   const statusMap = { | ||||||
|  |     '可用': 'success', | ||||||
|  |     '使用中': 'primary', | ||||||
|  |     '维修中': 'warning' | ||||||
|  |   }; | ||||||
|  |   return statusMap[status] || 'default'; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 搜索处理 | ||||||
|  | const handleSearch = () => { | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页事件 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 操作按钮事件 | ||||||
|  | const handleViewDetails = (row) => { | ||||||
|  |   console.log('查看详情:', row); | ||||||
|  |   // 实际应用中这里会跳转到详情页 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleDispatch = (row) => { | ||||||
|  |   console.log('调度车辆:', row); | ||||||
|  |   // 实际应用中这里会打开调度表单 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导航路由跳转 | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/cheliangzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/banzhuzhuangtai'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .execution-records { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 搜索和筛选区样式 */ | ||||||
|  | .search-filter { | ||||||
|  |   border-radius: 12px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); | ||||||
|  |   overflow: hidden; | ||||||
|  |   transition: box-shadow 0.3s ease; | ||||||
|  |   background: linear-gradient(135deg, #f0f7ff 0%, #f5f7fa 100%); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-container { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   padding: 24px 32px; | ||||||
|  |   min-height: 140px; | ||||||
|  |   position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计数据和车辆图片组合容器 */ | ||||||
|  | .stats-and-image { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   gap: 40px; | ||||||
|  |   flex: 1; | ||||||
|  |   max-width: calc(100% - 350px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 车辆统计区域 */ | ||||||
|  | .vehicle-stats { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 28px; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   position: relative; | ||||||
|  |   z-index: 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 搜索区域 */ | ||||||
|  | .search-integrated { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: flex-end; | ||||||
|  |   width: 320px; | ||||||
|  |   z-index: 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-box { | ||||||
|  |   border-radius: 12px; | ||||||
|  |   padding: 20px 24px; | ||||||
|  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); | ||||||
|  |   backdrop-filter: blur(10px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #2c3e50; | ||||||
|  |   margin-bottom: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-item { | ||||||
|  |   flex: 1; | ||||||
|  |  | ||||||
|  |   padding: 20px 28px; | ||||||
|  |   transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | ||||||
|  |   min-width: 160px; | ||||||
|  |   backdrop-filter: blur(10px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 32px; | ||||||
|  |   font-weight: 700; | ||||||
|  |   margin-bottom: 6px; | ||||||
|  |   line-height: 1.2; | ||||||
|  |   letter-spacing: -0.5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   margin-bottom: 4px; | ||||||
|  |   color: #2c3e50; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-desc { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #606266; | ||||||
|  |   opacity: 0.9; | ||||||
|  | } | ||||||
|  | .stats-container { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); | ||||||
|  |   display: inline-block; /* 适应内容宽度 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .vehicle-stats { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 40px; /* 统计项之间的间距 */ | ||||||
|  |   align-items: flex-start; /* 顶部对齐 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-item { | ||||||
|  |   text-align: center; | ||||||
|  |   min-width: 120px; /* 保证每个项的最小宽度 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: bold; | ||||||
|  |   color: #1f2937; /* 深色标题(与参考图一致) */ | ||||||
|  |   margin-bottom: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: bold; | ||||||
|  |   color: #1f2937; /* 深色数值(与参考图一致) */ | ||||||
|  |   margin-bottom: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-desc { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #6b7280; /* 浅灰色默认描述 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 不同状态的描述文字颜色 */ | ||||||
|  | .stat-desc.available { | ||||||
|  |   color: #059669; /* 绿色(可立即调度) */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-desc.in-use { | ||||||
|  |   color: #d97706; /* 橙色(执行任务中) */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-desc.maintenance { | ||||||
|  |   color: #dc2626; /* 红色(预计2天后可用) */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 车牌号输入样式 */ | ||||||
|  | .license-plate-input { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border: 2px solid #e6e6e6; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   overflow: hidden; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .license-plate-input:hover { | ||||||
|  |   border-color: #c0c4cc; | ||||||
|  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .plate-prefix { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   padding: 0 12px; | ||||||
|  |   height: 42px; | ||||||
|  |   line-height: 42px; | ||||||
|  |   border-right: 1px solid #dcdfe6; | ||||||
|  |   font-weight: 600; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #303133; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .plate-dot { | ||||||
|  |   padding: 0 6px; | ||||||
|  |   height: 42px; | ||||||
|  |   line-height: 42px; | ||||||
|  |   color: #606266; | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .plate-char { | ||||||
|  |   width: 32px !important; | ||||||
|  |   height: 42px !important; | ||||||
|  |   text-align: center; | ||||||
|  |   border: none; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   background-color: #fff; | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .plate-char:focus { | ||||||
|  |   background-color: #f0f7ff; | ||||||
|  |   color: #409eff; | ||||||
|  |   font-weight: 600; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .plate-char:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 表格样式优化 */ | ||||||
|  | .table-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 状态标签样式 */ | ||||||
|  | .status-tag { | ||||||
|  |   padding: 4px 10px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 操作按钮样式优化 */ | ||||||
|  | .action-btn { | ||||||
|  |   color: #165dff; | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding: 4px 10px; | ||||||
|  |   margin: 0 3px; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn:hover { | ||||||
|  |   color: #094ab2; | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .dispatch-btn { | ||||||
|  |   color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .dispatch-btn:hover { | ||||||
|  |   color: #389e0d; | ||||||
|  |   background-color: #f6ffed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .pagination-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 16px 24px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-info { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination { | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination button, | ||||||
|  | .pagination-controls .el-pagination .el-pager li { | ||||||
|  |   min-width: 36px; | ||||||
|  |   height: 36px; | ||||||
|  |   line-height: 36px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination .el-pager li.active { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   color: #fff; | ||||||
|  | } | ||||||
|  | .img-car { | ||||||
|  |   max-width: 400px; | ||||||
|  |   max-height: 200px; | ||||||
|  | } | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .search-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .stats-and-image { | ||||||
|  |     max-width: 100%; | ||||||
|  |     width: 100%; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .search-integrated { | ||||||
|  |     width: 100%; | ||||||
|  |     justify-content: flex-start; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 992px) { | ||||||
|  |   .stats-and-image { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .vehicle-image-container { | ||||||
|  |     width: 100%; | ||||||
|  |     max-width: 300px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .execution-records { | ||||||
|  |     padding: 10px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .navigation-tabs { | ||||||
|  |     flex-wrap: wrap; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .nav-tab { | ||||||
|  |     flex: 1 0 33%; | ||||||
|  |     padding: 10px 0; | ||||||
|  |     font-size: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .vehicle-stats { | ||||||
|  |     gap: 10px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .stat-item { | ||||||
|  |     flex: 1 0 40%; | ||||||
|  |     padding: 10px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .stat-value { | ||||||
|  |     font-size: 20px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .pagination-section { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |     gap: 10px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										1091
									
								
								src/views/zhinengxunjian/gongdanliebiao.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										842
									
								
								src/views/zhinengxunjian/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,842 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="box-container"> | ||||||
|  |       <!-- 导航栏 --> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <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"> | ||||||
|  |           <div class="calendar-header"> | ||||||
|  |             <div class="calendar-title">待办月视图</div> | ||||||
|  |             <div class="calendar-controls"> | ||||||
|  |               <!-- 月份选择器 --> | ||||||
|  |               <el-date-picker v-model="currentDate" type="month" placeholder="选择月份" style="width: 120px; margin-right: 15px" /> | ||||||
|  |  | ||||||
|  |               <el-button type="primary">添加</el-button> | ||||||
|  |               <el-button type="primary" @click="goToToday">今日</el-button> | ||||||
|  |               <el-button type="text" icon="el-icon-plus"></el-button> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |           <!-- 使用 Element Plus 的日历组件 --> | ||||||
|  |           <el-calendar v-model="currentDate"> | ||||||
|  |             <template #date-cell="{ date, data }"> | ||||||
|  |               <div class="custom-date-cell" :class="getCellClass(data.day)"> | ||||||
|  |                 <div class="date-day">{{ data.day.split('-').slice(2).join('-') }}</div> | ||||||
|  |                 <div class="date-events"> | ||||||
|  |                   <div v-for="event in getDayEvents(data.day)" :key="event.id" class="event-item" :class="'event-' + event.type"> | ||||||
|  |                     <div class="event-title">{{ event.title }}</div> | ||||||
|  |                     <div class="event-description">{{ event.description }}</div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </template> | ||||||
|  |           </el-calendar> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <!-- 右侧表单区域 --> | ||||||
|  |         <div class="form-container"> | ||||||
|  |           <div class="form-header"> | ||||||
|  |             <h2>今日待办</h2> | ||||||
|  |             <el-button type="primary" size="small" icon="el-icon-plus" @click="openAddTaskDialog">添加</el-button> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 待办事项列表 --> | ||||||
|  |           <div class="todo-list"> | ||||||
|  |             <!-- 待办项1 - 常规维护 --> | ||||||
|  |             <div class="todo-item"> | ||||||
|  |               <div class="todo-color-indicator normal"></div> | ||||||
|  |               <el-checkbox class="todo-checkbox"></el-checkbox> | ||||||
|  |               <div class="todo-content"> | ||||||
|  |                 <div class="todo-main"> | ||||||
|  |                   <div class="todo-title">服务器例行检查</div> | ||||||
|  |                   <div class="todo-time">09:00-10:00 AM</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div> | ||||||
|  |               </div> | ||||||
|  |               <div class="todo-actions"> | ||||||
|  |                 <button class="action-btn edit-btn" @click="handleEdit"> | ||||||
|  |                   <img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |                 <button class="action-btn delete-btn" @click="handleDelete"> | ||||||
|  |                   <img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <!-- 待办项2 - 重要 --> | ||||||
|  |             <div class="todo-item important"> | ||||||
|  |               <div class="todo-color-indicator important"></div> | ||||||
|  |               <el-checkbox class="todo-checkbox"></el-checkbox> | ||||||
|  |               <div class="todo-content"> | ||||||
|  |                 <div class="todo-main"> | ||||||
|  |                   <div class="todo-title">数据库备份</div> | ||||||
|  |                   <div class="todo-time">14:00-15:00 PM</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="todo-description">主要数据库全备份,并验证备份文件完整性</div> | ||||||
|  |               </div> | ||||||
|  |               <div class="todo-actions"> | ||||||
|  |                 <button class="action-btn edit-btn" @click="handleEdit"> | ||||||
|  |                   <img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |                 <button class="action-btn delete-btn" @click="handleDelete"> | ||||||
|  |                   <img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <!-- 待办项3 - 紧急 --> | ||||||
|  |             <div class="todo-item"> | ||||||
|  |               <div class="todo-color-indicator urgent"></div> | ||||||
|  |               <el-checkbox class="todo-checkbox"></el-checkbox> | ||||||
|  |               <div class="todo-content"> | ||||||
|  |                 <div class="todo-main"> | ||||||
|  |                   <div class="todo-title">网络设备固件更新</div> | ||||||
|  |                   <div class="todo-time">18:00-20:00 PM</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="todo-description">更新核心交换机和防火墙固件,需安排在业务低峰期</div> | ||||||
|  |               </div> | ||||||
|  |               <div class="todo-actions"> | ||||||
|  |                 <button class="action-btn edit-btn" @click="handleEdit"> | ||||||
|  |                   <img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |                 <button class="action-btn delete-btn" @click="handleDelete"> | ||||||
|  |                   <img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <!-- 待办项4 - 常规维护 --> | ||||||
|  |             <div class="todo-item"> | ||||||
|  |               <div class="todo-color-indicator normal"></div> | ||||||
|  |               <el-checkbox class="todo-checkbox"></el-checkbox> | ||||||
|  |               <div class="todo-content"> | ||||||
|  |                 <div class="todo-main"> | ||||||
|  |                   <div class="todo-title">服务器例行检查</div> | ||||||
|  |                   <div class="todo-time">08:00-09:00 AM</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div> | ||||||
|  |               </div> | ||||||
|  |               <div class="todo-actions"> | ||||||
|  |                 <button class="action-btn edit-btn" @click="handleEdit"> | ||||||
|  |                   <img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |                 <button class="action-btn delete-btn" @click="handleDelete"> | ||||||
|  |                   <img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div class="todo-item"> | ||||||
|  |               <div class="todo-color-indicator normal"></div> | ||||||
|  |               <el-checkbox class="todo-checkbox"></el-checkbox> | ||||||
|  |               <div class="todo-content"> | ||||||
|  |                 <div class="todo-main"> | ||||||
|  |                   <div class="todo-title">服务器例行检查</div> | ||||||
|  |                   <div class="todo-time">06:00-07:00 AM</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div> | ||||||
|  |               </div> | ||||||
|  |               <div class="todo-actions"> | ||||||
|  |                 <button class="action-btn edit-btn" @click="handleEdit"> | ||||||
|  |                   <img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |                 <button class="action-btn delete-btn" @click="handleDelete"> | ||||||
|  |                   <img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div class="todo-item"> | ||||||
|  |               <div class="todo-color-indicator normal"></div> | ||||||
|  |               <el-checkbox class="todo-checkbox"></el-checkbox> | ||||||
|  |               <div class="todo-content"> | ||||||
|  |                 <div class="todo-main"> | ||||||
|  |                   <div class="todo-title">服务器例行检查</div> | ||||||
|  |                   <div class="todo-time">06:00-07:00 AM</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div> | ||||||
|  |               </div> | ||||||
|  |               <div class="todo-actions"> | ||||||
|  |                 <button class="action-btn edit-btn" @click="handleEdit"> | ||||||
|  |                   <img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |                 <button class="action-btn delete-btn" @click="handleDelete"> | ||||||
|  |                   <img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 状态图例 - 标签形式 --> | ||||||
|  |           <div class="status-legend"> | ||||||
|  |             <span class="status-tag normal"><span class="color-block"></span>常规维护</span> | ||||||
|  |             <span class="status-tag important"><span class="color-block"></span>重要</span> | ||||||
|  |             <span class="status-tag urgent"><span class="color-block"></span>紧急</span> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |       <el-dialog v-model="dialogVisible" title="新增任务" 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> | ||||||
|  |           </el-form-item> | ||||||
|  |           <el-form-item label="任务描述" prop="description"> | ||||||
|  |             <el-input v-model="taskForm.description" placeholder="输入任务描述" class="form-input"></el-input> | ||||||
|  |           </el-form-item> | ||||||
|  |           <el-form-item label="时间" prop="timeRange"> | ||||||
|  |             <el-date-picker | ||||||
|  |               v-model="taskForm.timeRange" | ||||||
|  |               type="datetimerange" | ||||||
|  |               start-placeholder="开始时间" | ||||||
|  |               end-placeholder="结束时间" | ||||||
|  |               class="form-input" | ||||||
|  |               style="width: 100%" | ||||||
|  |             /> | ||||||
|  |           </el-form-item> | ||||||
|  |           <el-form-item label="优先级" prop="priority"> | ||||||
|  |             <el-select v-model="taskForm.priority" placeholder="选择优先级" class="form-input"> | ||||||
|  |               <el-option label="常规项" value="常规项"></el-option> | ||||||
|  |               <el-option label="重要" value="重要"></el-option> | ||||||
|  |               <el-option label="紧急" value="紧急"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |           <el-form-item label="任务类型" prop="taskType"> | ||||||
|  |             <el-select v-model="taskForm.taskType" placeholder="选择任务类型" class="form-input"> | ||||||
|  |               <el-option label="常规维护" value="常规维护"></el-option> | ||||||
|  |               <el-option label="安全巡检" value="安全巡检"></el-option> | ||||||
|  |               <el-option label="系统升级" value="系统升级"></el-option> | ||||||
|  |               <el-option label="数据备份" value="数据备份"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |         </el-form> | ||||||
|  |         <template #footer> | ||||||
|  |           <el-button @click="closeDialog">取消</el-button> | ||||||
|  |           <el-button type="primary" @click="saveTask">保存任务</el-button> | ||||||
|  |         </template> | ||||||
|  |       </el-dialog> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed, watch } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 默认显示当前月份 | ||||||
|  | const currentDate = ref(new Date()); | ||||||
|  |  | ||||||
|  | // 为了保持兼容性,保留这些变量 | ||||||
|  | const targetYear = 2025; | ||||||
|  | const years = ref([]); | ||||||
|  | const selectedYear = ref(currentDate.value.getFullYear()); | ||||||
|  | const selectedMonth = ref(currentDate.value.getMonth() + 1); | ||||||
|  |  | ||||||
|  | // 减少月份 | ||||||
|  | const decreaseMonth = () => { | ||||||
|  |   const date = new Date(currentDate.value); | ||||||
|  |   date.setMonth(date.getMonth() - 1); | ||||||
|  |   currentDate.value = date; | ||||||
|  |   updateYearAndMonth(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 增加月份 | ||||||
|  | const increaseMonth = () => { | ||||||
|  |   const date = new Date(currentDate.value); | ||||||
|  |   date.setMonth(date.getMonth() + 1); | ||||||
|  |   currentDate.value = date; | ||||||
|  |   updateYearAndMonth(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 回到今天 | ||||||
|  | const goToToday = () => { | ||||||
|  |   currentDate.value = new Date(); | ||||||
|  |   updateYearAndMonth(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 日历事件数据 - 2025年9月的随机事件 | ||||||
|  | const calendarEvents = ref([ | ||||||
|  |   // 服务维护事件 | ||||||
|  |   { id: 1, date: '2025-09-11', title: '服务维护', description: '维护公司内部服务器', type: 'service' }, | ||||||
|  |   { id: 2, date: '2025-09-28', title: '服务维护', description: '先所有旧服务器部署新内存', type: 'service' }, | ||||||
|  |  | ||||||
|  |   // 数据库管理事件 | ||||||
|  |   { id: 3, date: '2025-09-21', title: '数据库管理', description: '定期执行数据库优化', type: 'database' }, | ||||||
|  |   { id: 4, date: '2025-09-30', title: '数据库管理', description: '大型数据库备份策略', type: 'database' }, | ||||||
|  |  | ||||||
|  |   // 网络维护事件 | ||||||
|  |   { id: 5, date: '2025-09-05', title: '网络维护', description: '网络设备例行检查', type: 'network' }, | ||||||
|  |   { id: 6, date: '2025-09-15', title: '网络维护', description: '更新网络安全策略', type: 'network' }, | ||||||
|  |  | ||||||
|  |   // 系统升级事件 | ||||||
|  |   { id: 7, date: '2025-09-18', title: '系统升级', description: '核心系统版本升级', type: 'upgrade' }, | ||||||
|  |   { id: 8, date: '2025-09-25', title: '系统升级', description: '应用服务升级部署', type: 'upgrade' } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 获取指定日期的事件 | ||||||
|  | const getDayEvents = (dateStr) => { | ||||||
|  |   return calendarEvents.value.filter((event) => event.date === dateStr); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 根据事件类型获取单元格样式 | ||||||
|  | const getCellClass = (date) => { | ||||||
|  |   const events = getDayEvents(date); | ||||||
|  |   if (events.length > 0) { | ||||||
|  |     const eventType = events[0].type; | ||||||
|  |     return `date-cell-${eventType}`; | ||||||
|  |   } | ||||||
|  |   return ''; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 更新年份和月份选择器的值 | ||||||
|  | const updateYearAndMonth = () => { | ||||||
|  |   selectedYear.value = currentDate.value.getFullYear(); | ||||||
|  |   selectedMonth.value = currentDate.value.getMonth() + 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 监听日期变化,更新年份和月份 | ||||||
|  | watch(currentDate, (newDate) => { | ||||||
|  |   selectedYear.value = newDate.getFullYear(); | ||||||
|  |   selectedMonth.value = newDate.getMonth() + 1; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 初始化年份和月份 | ||||||
|  | updateYearAndMonth(); | ||||||
|  |  | ||||||
|  | // 弹窗相关状态管理 | ||||||
|  | const dialogVisible = ref(false); | ||||||
|  | const taskForm = ref({ | ||||||
|  |   name: '', | ||||||
|  |   description: '', | ||||||
|  |   timeRange: '', | ||||||
|  |   priority: '常规项', | ||||||
|  |   taskType: '常规维护' | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 打开添加任务弹窗 | ||||||
|  | const openAddTaskDialog = () => { | ||||||
|  |   dialogVisible.value = true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 关闭弹窗 | ||||||
|  | const closeDialog = () => { | ||||||
|  |   dialogVisible.value = false; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 保存任务 | ||||||
|  | const saveTask = () => { | ||||||
|  |   // 这里可以添加表单验证和保存逻辑 | ||||||
|  |   console.log('保存任务:', taskForm.value); | ||||||
|  |   // 重置表单 | ||||||
|  |   taskForm.value = { | ||||||
|  |     name: '', | ||||||
|  |     description: '', | ||||||
|  |     timeRange: '', | ||||||
|  |     priority: '常规项', | ||||||
|  |     taskType: '常规维护' | ||||||
|  |   }; | ||||||
|  |   // 关闭弹窗 | ||||||
|  |   closeDialog(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 编辑和删除处理函数 | ||||||
|  | const handleEdit = () => { | ||||||
|  |   console.log('执行编辑操作'); | ||||||
|  |   // 保留原有编辑逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleDelete = () => { | ||||||
|  |   console.log('执行删除操作'); | ||||||
|  |   // 保留原有删除逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .box-container { | ||||||
|  |   width: 100%; | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   cursor: pointer; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header { | ||||||
|  |   margin-bottom: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header h1 { | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header p { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   margin: 5px 0 0 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .main-content { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 20px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 日历区域样式 */ | ||||||
|  | .calendar-container { | ||||||
|  |   flex: 1; | ||||||
|  |   min-width: 0; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   padding: 20px; | ||||||
|  |   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | ||||||
|  |   height: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 自定义弹窗样式 */ | ||||||
|  | .custom-dialog { | ||||||
|  |   border-radius: 8px; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-dialog .el-dialog__header { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   border-bottom: 1px solid #e4e7ed; | ||||||
|  |   padding: 15px 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-dialog .el-dialog__title { | ||||||
|  |   font-size: 16px; | ||||||
|  |   color: #303133; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-dialog .el-dialog__body { | ||||||
|  |   padding: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 确保所有输入框长度相等 */ | ||||||
|  | .task-form .form-input { | ||||||
|  |   height: 30px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 时间选择器样式调整 */ | ||||||
|  | .task-form .el-date-editor { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 30px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .calendar-header { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .calendar-title { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #303133; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .calendar-controls { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .el-select { | ||||||
|  |   margin-right: 5px; | ||||||
|  | } | ||||||
|  | .form-container { | ||||||
|  |   flex: 0 0 360px; /* 调整宽度以匹配设计图,更贴合右侧区域宽度 */ | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   padding: 20px 20px 80px 20px; /* 增加底部内边距,为固定标签留出空间 */ | ||||||
|  |   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | ||||||
|  |   position: relative; /* 设置为相对定位,使内部绝对定位元素相对于此容器定位 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .form-header { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   padding-bottom: 10px; | ||||||
|  |   border-bottom: 1px solid #f0f0f0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .form-header h2 { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-list { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   gap: 10px; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   max-height: 480px; | ||||||
|  |   overflow-y: auto; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-item { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   gap: 10px; | ||||||
|  |   padding: 12px 12px 12px 20px; | ||||||
|  |   background-color: #fafafa; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   position: relative; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 重要任务的背景色 */ | ||||||
|  | .todo-item.important { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-checkbox { | ||||||
|  |   margin-top: 2px; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-content { | ||||||
|  |   flex: 1; | ||||||
|  |   position: relative; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-main { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-bottom: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-title { | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #303133; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-time { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #909399; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-description { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #606266; | ||||||
|  |   line-height: 1.4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-actions { | ||||||
|  |   position: absolute; | ||||||
|  |   right: -80px; | ||||||
|  |   top: 0; | ||||||
|  |   bottom: 0; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   gap: 8px; | ||||||
|  |   padding: 0 12px; | ||||||
|  |   background-color: inherit; | ||||||
|  |   opacity: 0; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn { | ||||||
|  |   width: 36px; | ||||||
|  |   height: 36px; | ||||||
|  |   border: none; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   cursor: pointer; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: center; | ||||||
|  |   padding: 0; | ||||||
|  |   background-color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn:hover { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   transform: translateY(-1px); | ||||||
|  |   box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 悬停显示操作按钮 */ | ||||||
|  | .todo-item:hover .todo-actions { | ||||||
|  |   opacity: 1; | ||||||
|  |   right: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 内容区域平移以给按钮留出空间 */ | ||||||
|  | .todo-item:hover .todo-content { | ||||||
|  |   transform: translateX(-80px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-icon { | ||||||
|  |   width: 16px; | ||||||
|  |   height: 16px; | ||||||
|  |   object-fit: contain; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 调整按钮间距 */ | ||||||
|  | .todo-actions { | ||||||
|  |   gap: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-legend { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 20px; | ||||||
|  |   padding: 15px 0; | ||||||
|  |   border-top: 1px solid #ebeef5; | ||||||
|  |   justify-content: center; | ||||||
|  |   width: 100%; | ||||||
|  |   position: absolute; | ||||||
|  |   bottom: 0; | ||||||
|  |   left: 0; | ||||||
|  |   right: 0; | ||||||
|  |   background-color: #fff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag { | ||||||
|  |   display: inline-flex; | ||||||
|  |   align-items: center; | ||||||
|  |   gap: 5px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #303133; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag .color-block { | ||||||
|  |   width: 12px; | ||||||
|  |   height: 12px; | ||||||
|  |   border-radius: 2px; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.normal .color-block { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  | .status-tag.important .color-block { | ||||||
|  |   background-color: #faad14; | ||||||
|  | } | ||||||
|  | .status-tag.urgent .color-block { | ||||||
|  |   background-color: #ff4d4f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-color-indicator { | ||||||
|  |   width: 8px; | ||||||
|  |   height: 100%; | ||||||
|  |   border-radius: 0 4px 4px 0; | ||||||
|  |   position: absolute; | ||||||
|  |   left: 0; | ||||||
|  |   top: 0; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-color-indicator.normal { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-color-indicator.important { | ||||||
|  |   background-color: #faad14; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-color-indicator.urgent { | ||||||
|  |   background-color: #ff4d4f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ::v-deep .custom-date-cell { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 100%; | ||||||
|  |   padding: 5px; | ||||||
|  |   text-align: center; | ||||||
|  |   box-sizing: border-box; /* 确保内边距不撑大元素 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 系统升级事件样式 */ | ||||||
|  | .event-upgrade { | ||||||
|  |   background-color: #fff1f0; | ||||||
|  |   color: #f5222d; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 日期单元格背景色 - 按事件类型 */ | ||||||
|  | .date-cell-service { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .date-cell-database { | ||||||
|  |   background-color: #f0f9ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .date-cell-network { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .date-cell-upgrade { | ||||||
|  |   background-color: #fff1f0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 日历样式优化 */ | ||||||
|  | .el-calendar { | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .el-calendar-table { | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 穿透作用域,强制设置日历单元格为正方形 */ | ||||||
|  | ::v-deep .el-calendar-table td { | ||||||
|  |   padding: 2px; | ||||||
|  |   vertical-align: top; | ||||||
|  |   width: 120px; /* 强制宽度 */ | ||||||
|  |   height: 120px; /* 强制高度(与宽度一致) */ | ||||||
|  | } | ||||||
|  | ::v-deep .el-calendar-day { | ||||||
|  |   padding: 0; /* 移除默认内边距 */ | ||||||
|  |   width: 100%; | ||||||
|  |   height: 100%; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   overflow: hidden; | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .date-day { | ||||||
|  |   font-weight: bold; | ||||||
|  |   margin-bottom: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .date-events { | ||||||
|  |   flex: 1; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .event-item { | ||||||
|  |   padding: 3px; | ||||||
|  |   margin-bottom: 2px; | ||||||
|  |   border-radius: 3px; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .event-title { | ||||||
|  |   font-weight: bold; | ||||||
|  |   white-space: nowrap; | ||||||
|  |   overflow: hidden; | ||||||
|  |   text-overflow: ellipsis; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .event-description { | ||||||
|  |   font-size: 11px; | ||||||
|  |   white-space: nowrap; | ||||||
|  |   overflow: hidden; | ||||||
|  |   text-overflow: ellipsis; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 服务维护事件样式 */ | ||||||
|  | .event-service { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  |   color: #1890ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 数据库管理事件样式 */ | ||||||
|  | .event-database { | ||||||
|  |   background-color: #f0f9ff; | ||||||
|  |   color: #36cfc9; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 网络维护事件样式 */ | ||||||
|  | .event-network { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #faad14; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 系统升级事件样式 */ | ||||||
|  | .event-upgrade { | ||||||
|  |   background-color: #fff1f0; | ||||||
|  |   color: #f5222d; | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										824
									
								
								src/views/zhinengxunjian/paidanjilu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,824 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="dispatch-records"> | ||||||
|  |       <!-- 顶部导航栏 --> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 页面标题 --> | ||||||
|  |       <TitleComponent title="工单管理模块" subtitle="发起工单任务,跟踪流程记录和执行情况"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">工单列表</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">派单计划</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement3">执行计划</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 筛选栏 --> | ||||||
|  |       <div class="filter-bar"> | ||||||
|  |         <div class="filter-container"> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="dispatchStatus" placeholder="派单状态" clearable> | ||||||
|  |               <el-option label="全部状态" value="all"></el-option> | ||||||
|  |               <el-option label="已接收" value="received"></el-option> | ||||||
|  |               <el-option label="处理中" value="processing"></el-option> | ||||||
|  |               <el-option label="已完成" value="completed"></el-option> | ||||||
|  |               <el-option label="已拒绝" value="rejected"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="executor" placeholder="执行人" clearable> | ||||||
|  |               <el-option label="全部人员" value="all"></el-option> | ||||||
|  |               <el-option label="张明" value="zhangming"></el-option> | ||||||
|  |               <el-option label="李华" value="lihua"></el-option> | ||||||
|  |               <el-option label="王强" value="wangqiang"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-date-picker v-model="dispatchDate" type="date" placeholder="派单日期" format="yyyy/MM/dd" value-format="yyyy/MM/dd"></el-date-picker> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-actions"> | ||||||
|  |             <el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button> | ||||||
|  |             <el-button type="primary" class="create-btn" @click="handleExport">导出记录</el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 统计卡片 --> | ||||||
|  |       <div class="statistics-cards"> | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-value">{{ totalDispatches }}</div> | ||||||
|  |           <div class="stat-label">本月派单总数</div> | ||||||
|  |           <div class="stat-trend">较上月 <span class="trend-up">↑ 12%</span></div> | ||||||
|  |           <div class="stat-icon"> | ||||||
|  |             <img src="@/assets/images/paidan.png" alt="时间" class="stat-img" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-value">{{ avgResponseTime }}</div> | ||||||
|  |           <div class="stat-label">平均响应时间</div> | ||||||
|  |           <div class="stat-trend">较上月 <span class="trend-down">↓ 5分钟</span></div> | ||||||
|  |           <div class="stat-icon"> | ||||||
|  |             <img src="@/assets/images/shijian.png" alt="时间" class="stat-img" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-value">{{ pendingDispatches }}</div> | ||||||
|  |           <div class="stat-label">待接收工单</div> | ||||||
|  |           <div class="stat-trend">较昨日 <span class="trend-up">↑ 2</span></div> | ||||||
|  |           <div class="stat-icon warning"> | ||||||
|  |             <img src="@/assets/images/gongdan.png" alt="工单" class="stat-img" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-value">{{ completionRate }}</div> | ||||||
|  |           <div class="stat-label">按时完成率</div> | ||||||
|  |           <div class="stat-trend">较上月 <span class="trend-up">↑ 3%</span></div> | ||||||
|  |           <div class="stat-icon success"> | ||||||
|  |             <img src="@/assets/images/wancheng.png" alt="完成" class="stat-img" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 派单记录表格 --> | ||||||
|  |       <div class="table-wrapper"> | ||||||
|  |         <el-table :data="pagedTableData" stripe style="width: 100%" highlight-current-row class="custom-table"> | ||||||
|  |           <el-table-column align="center" prop="dispatchNo" label="派单号" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="orderNo" label="工单编号" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="taskType" label="工单类型" min-width="100"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="dispatcher" label="派单人" min-width="100"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="executor" label="接收人" min-width="100"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="dispatchTime" label="派单时间" min-width="140"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="status" label="派单状态" min-width="100"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-tag :type="getStatusTagType(scope.row.status)" class="status-tag"> | ||||||
|  |                 {{ scope.row.status }} | ||||||
|  |               </el-tag> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |           <el-table-column align="center" prop="completionStatus" label="完成状态" min-width="100"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-tag :type="getCompletionTagType(scope.row.completionStatus)" class="completion-tag"> | ||||||
|  |                 {{ scope.row.completionStatus }} | ||||||
|  |               </el-tag> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |           <el-table-column align="center" label="操作" min-width="180" fixed="right"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-button type="text" @click="handleViewDetails(scope.row)" class="action-btn">详情</el-button> | ||||||
|  |               <el-button | ||||||
|  |                 type="text" | ||||||
|  |                 @click="handleViewReport(scope.row)" | ||||||
|  |                 class="action-btn report-btn" | ||||||
|  |                 v-if="scope.row.completionStatus === '已完成'" | ||||||
|  |               > | ||||||
|  |                 查看报告 | ||||||
|  |               </el-button> | ||||||
|  |               <el-button | ||||||
|  |                 type="text" | ||||||
|  |                 @click="handleViewProgress(scope.row)" | ||||||
|  |                 class="action-btn progress-btn" | ||||||
|  |                 v-else-if="scope.row.completionStatus === '进行中'" | ||||||
|  |               > | ||||||
|  |                 查看进度 | ||||||
|  |               </el-button> | ||||||
|  |               <el-button type="text" @click="handleTrack(scope.row)" class="action-btn track-btn" v-else> 跟踪 </el-button> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |         </el-table> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-info"> | ||||||
|  |           显示第{{ (currentPage - 1) * pageSize + 1 }}到{{ Math.min(currentPage * pageSize, total) }}条,共{{ total }}条记录 | ||||||
|  |         </div> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[10, 20, 30, 40]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed, reactive } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 激活的选项卡,默认显示派单记录 | ||||||
|  | const activeTab = ref('dispatch'); | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const dispatchStatus = ref('all'); | ||||||
|  | const executor = ref('all'); | ||||||
|  | const dispatchDate = ref(''); | ||||||
|  |  | ||||||
|  | // 统计数据 | ||||||
|  | const totalDispatches = ref(56); | ||||||
|  | const avgResponseTime = ref('42分钟'); | ||||||
|  | const pendingDispatches = ref(7); | ||||||
|  | const completionRate = ref('92%'); | ||||||
|  |  | ||||||
|  | // 派单记录数据 | ||||||
|  | const rawTableData = ref([ | ||||||
|  |   { | ||||||
|  |     dispatchNo: 'DP-2023-0619-089', | ||||||
|  |     orderNo: 'WO-2023-0619-055', | ||||||
|  |     taskType: '安全设备检查检测', | ||||||
|  |     dispatcher: '张明', | ||||||
|  |     executor: '李阳', | ||||||
|  |     dispatchTime: '2023-06-19 13:50', | ||||||
|  |     status: '已接收', | ||||||
|  |     completionStatus: '未完成' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     dispatchNo: 'DP-2023-0619-088', | ||||||
|  |     orderNo: 'WO-2023-0618-054', | ||||||
|  |     taskType: '新设备安装调试', | ||||||
|  |     dispatcher: '张明', | ||||||
|  |     executor: '李阳', | ||||||
|  |     dispatchTime: '2023-06-19 13:30', | ||||||
|  |     status: '已接收', | ||||||
|  |     completionStatus: '进行中' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     dispatchNo: 'DP-2023-0619-087', | ||||||
|  |     orderNo: 'WO-2023-0617-053', | ||||||
|  |     taskType: '系统升级改造', | ||||||
|  |     dispatcher: '张明', | ||||||
|  |     executor: '李阳', | ||||||
|  |     dispatchTime: '2023-06-19 10:15', | ||||||
|  |     status: '已接收', | ||||||
|  |     completionStatus: '已完成' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     dispatchNo: 'DP-2023-0619-086', | ||||||
|  |     orderNo: 'WO-2023-0616-052', | ||||||
|  |     taskType: '安全设备检查检测', | ||||||
|  |     dispatcher: '张明', | ||||||
|  |     executor: '李阳', | ||||||
|  |     dispatchTime: '2023-06-19 09:40', | ||||||
|  |     status: '已接收', | ||||||
|  |     completionStatus: '未完成' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     dispatchNo: 'DP-2023-0619-085', | ||||||
|  |     orderNo: 'WO-2023-0615-051', | ||||||
|  |     taskType: '安全设备检查检测', | ||||||
|  |     dispatcher: '张明', | ||||||
|  |     executor: '李阳', | ||||||
|  |     dispatchTime: '2023-06-19 09:20', | ||||||
|  |     status: '已接收', | ||||||
|  |     completionStatus: '未完成' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     dispatchNo: 'DP-2023-0619-084', | ||||||
|  |     orderNo: 'WO-2023-0614-050', | ||||||
|  |     taskType: '安全设备检查检测', | ||||||
|  |     dispatcher: '张明', | ||||||
|  |     executor: '李阳', | ||||||
|  |     dispatchTime: '2023-06-19 09:10', | ||||||
|  |     status: '已接收', | ||||||
|  |     completionStatus: '未完成' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     dispatchNo: 'DP-2023-0619-083', | ||||||
|  |     orderNo: 'WO-2023-0613-049', | ||||||
|  |     taskType: '安全设备检查检测', | ||||||
|  |     dispatcher: '张明', | ||||||
|  |     executor: '李阳', | ||||||
|  |     dispatchTime: '2023-06-19 08:50', | ||||||
|  |     status: '已接收', | ||||||
|  |     completionStatus: '未完成' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 分页相关 | ||||||
|  | const currentPage = ref(1); | ||||||
|  | const pageSize = ref(10); | ||||||
|  | const total = ref(rawTableData.value.length); | ||||||
|  |  | ||||||
|  | // 分页处理后的数据 | ||||||
|  | const pagedTableData = computed(() => { | ||||||
|  |   // 筛选逻辑 | ||||||
|  |   let filteredData = [...rawTableData.value]; | ||||||
|  |  | ||||||
|  |   if (dispatchStatus.value !== 'all') { | ||||||
|  |     filteredData = filteredData.filter((item) => item.status === dispatchStatus.value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (executor.value !== 'all') { | ||||||
|  |     // 这里假设执行人的值与选项值对应 | ||||||
|  |     const executorMap = { | ||||||
|  |       'zhangming': '张明', | ||||||
|  |       'lihua': '李华', | ||||||
|  |       'wangqiang': '王强' | ||||||
|  |     }; | ||||||
|  |     filteredData = filteredData.filter((item) => item.executor === executorMap[executor.value]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (dispatchDate.value) { | ||||||
|  |     filteredData = filteredData.filter((item) => item.dispatchTime.includes(dispatchDate.value)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // 更新总条数 | ||||||
|  |   total.value = filteredData.length; | ||||||
|  |  | ||||||
|  |   // 分页处理 | ||||||
|  |   const startIndex = (currentPage.value - 1) * pageSize.value; | ||||||
|  |   const endIndex = startIndex + pageSize.value; | ||||||
|  |   return filteredData.slice(startIndex, endIndex); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 获取派单状态标签样式 | ||||||
|  | const getStatusTagType = (status) => { | ||||||
|  |   const statusMap = { | ||||||
|  |     '已接收': 'primary', | ||||||
|  |     '处理中': 'success', | ||||||
|  |     '已完成': 'info', | ||||||
|  |     '已拒绝': 'danger' | ||||||
|  |   }; | ||||||
|  |   return statusMap[status] || 'default'; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 获取完成状态标签样式 | ||||||
|  | const getCompletionTagType = (status) => { | ||||||
|  |   const statusMap = { | ||||||
|  |     '未完成': 'warning', | ||||||
|  |     '进行中': 'primary', | ||||||
|  |     '已完成': 'success', | ||||||
|  |     '已逾期': 'danger' | ||||||
|  |   }; | ||||||
|  |   return statusMap[status] || 'default'; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 搜索处理 | ||||||
|  | const handleSearch = () => { | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导出记录 | ||||||
|  | const handleExport = () => { | ||||||
|  |   console.log('导出派单记录'); | ||||||
|  |   // 实际应用中这里会调用导出API | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页事件 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 选项卡点击 | ||||||
|  | const handleTabClick = (tab) => { | ||||||
|  |   console.log('切换到选项卡:', tab.name); | ||||||
|  |   // 重置筛选条件和分页 | ||||||
|  |   dispatchStatus.value = 'all'; | ||||||
|  |   executor.value = 'all'; | ||||||
|  |   dispatchDate.value = ''; | ||||||
|  |   currentPage.value = 1; | ||||||
|  |  | ||||||
|  |   // 如果切换到其他选项卡,导航到相应页面 | ||||||
|  |   if (tab.name === 'list') { | ||||||
|  |     router.push('/rili/gongdanguanli'); | ||||||
|  |   } else if (tab.name === 'execution') { | ||||||
|  |     router.push('/rili/execution-records'); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 操作按钮事件 | ||||||
|  | const handleViewDetails = (row) => { | ||||||
|  |   console.log('查看派单详情:', row); | ||||||
|  |   // 实际应用中这里会跳转到详情页 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleViewReport = (row) => { | ||||||
|  |   console.log('查看报告:', row); | ||||||
|  |   // 实际应用中这里会跳转到报告页面 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleViewProgress = (row) => { | ||||||
|  |   console.log('查看进度:', row); | ||||||
|  |   // 实际应用中这里会跳转到进度页面 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleTrack = (row) => { | ||||||
|  |   console.log('跟踪工单:', row); | ||||||
|  |   // 实际应用中这里会跳转到跟踪页面或打开跟踪弹窗 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导航路由跳转 | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/paidanjilu'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/zhixingjilu'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .dispatch-records { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs { | ||||||
|  |   padding-top: 1px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__header { | ||||||
|  |   margin: 0 -20px; | ||||||
|  |   padding: 0 20px; | ||||||
|  |   border-bottom: 1px solid #e4e7ed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__nav-wrap::after { | ||||||
|  |   height: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   padding: 14px 20px; | ||||||
|  |   margin-right: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item.is-active { | ||||||
|  |   color: #165dff; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item:hover { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-container { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select, | ||||||
|  | .filter-bar .el-date-picker { | ||||||
|  |   width: 180px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select .el-input__inner, | ||||||
|  | .filter-bar .el-date-picker .el-input__inner { | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border-color: #dcdfe6; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select .el-input__inner:focus, | ||||||
|  | .filter-bar .el-date-picker .el-input__inner:focus { | ||||||
|  |   border-color: #165dff; | ||||||
|  |   box-shadow: 0 0 0 2px rgba(22, 93, 255, 0.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 12px; | ||||||
|  |   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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .export-btn { | ||||||
|  |   color: #165dff; | ||||||
|  |   border: 1px solid #165dff; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .export-btn:hover { | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  |   color: #0e42d2; | ||||||
|  |   border-color: #0e42d2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计卡片样式 */ | ||||||
|  | .statistics-cards { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | ||||||
|  |   gap: 16px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-card { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 12px; | ||||||
|  |   padding: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   position: relative; | ||||||
|  |   overflow: hidden; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-card:hover { | ||||||
|  |   transform: translateY(-2px); | ||||||
|  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 28px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #1d2129; | ||||||
|  |   margin-bottom: 8px; | ||||||
|  |   line-height: 1.2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #86909c; | ||||||
|  |   margin-bottom: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .trend-up { | ||||||
|  |   color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .trend-down { | ||||||
|  |   color: #ff4d4f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-icon { | ||||||
|  |   position: absolute; | ||||||
|  |   top: 24px; | ||||||
|  |   right: 24px; | ||||||
|  |   width: 50px; | ||||||
|  |   height: 50px; | ||||||
|  |   border-radius: 12px; | ||||||
|  |   background-color: #f0f7ff; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: center; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-icon:hover { | ||||||
|  |   transform: scale(1.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计卡片图片样式 */ | ||||||
|  | .stat-img { | ||||||
|  |   width: 35px; | ||||||
|  |   height: 35px; | ||||||
|  |   object-fit: contain; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-icon:hover .stat-img { | ||||||
|  |   transform: scale(1.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 表格样式 */ | ||||||
|  | .table-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table { | ||||||
|  |   border-collapse: collapse; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table th { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #606266; | ||||||
|  |   text-align: center; | ||||||
|  |   padding: 12px 8px; | ||||||
|  |   border-bottom: 1px solid #e4e7ed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table td { | ||||||
|  |   padding: 12px 8px; | ||||||
|  |   border-bottom: 1px solid #e4e7ed; | ||||||
|  |   color: #303133; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table tr:hover { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-table tr.current-row { | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag, | ||||||
|  | .completion-tag { | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 操作按钮样式 */ | ||||||
|  | .action-btn { | ||||||
|  |   font-size: 12px; | ||||||
|  |   padding: 4px 8px; | ||||||
|  |   margin: 0 2px; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn:hover { | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .report-btn { | ||||||
|  |   color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .report-btn:hover { | ||||||
|  |   color: #389e0d; | ||||||
|  |   background-color: #f6ffed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-btn:hover { | ||||||
|  |   color: #0e42d2; | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .track-btn { | ||||||
|  |   color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .track-btn:hover { | ||||||
|  |   color: #e67700; | ||||||
|  |   background-color: #fff7e6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .pagination-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 16px 24px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-info { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination { | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination button, | ||||||
|  | .pagination-controls .el-pagination .el-pager li { | ||||||
|  |   min-width: 36px; | ||||||
|  |   height: 36px; | ||||||
|  |   line-height: 36px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination .el-pager li.active { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   color: #fff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   cursor: pointer; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .filter-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-actions { | ||||||
|  |     margin-left: 0; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-bar .el-select, | ||||||
|  |   .filter-bar .el-date-picker { | ||||||
|  |     width: 100%; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .create-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .create-btn:hover { | ||||||
|  |   background-color: #0e42d2; | ||||||
|  |   border-color: #0e42d2; | ||||||
|  | } | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .dispatch-records { | ||||||
|  |     padding: 10px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .navigation-tabs { | ||||||
|  |     flex-wrap: wrap; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .nav-tab { | ||||||
|  |     flex: 1 0 33%; | ||||||
|  |     padding: 10px 0; | ||||||
|  |     font-size: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .statistics-cards { | ||||||
|  |     grid-template-columns: 1fr 1fr; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .pagination-section { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |     gap: 10px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 480px) { | ||||||
|  |   .statistics-cards { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										936
									
								
								src/views/zhinengxunjian/qiangxiuguanli.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,936 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="inspection-tasks"> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |       <!-- 页面标题 --> | ||||||
|  |       <TitleComponent title="抢修管理模块" subtitle="处理紧急抢修任务,跟踪抢修进度和记录"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">抢修任务</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">抢修记录</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 筛选栏 --> | ||||||
|  |       <div class="filter-bar"> | ||||||
|  |         <div class="filter-container"> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="taskStatus" placeholder="任务状态"> | ||||||
|  |               <el-option label="待执行" value="pending"></el-option> | ||||||
|  |               <el-option label="执行中" value="executing"></el-option> | ||||||
|  |               <el-option label="已延期" value="delayed"></el-option> | ||||||
|  |               <el-option label="已完成" value="completed"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="planType" placeholder="全部计划"> | ||||||
|  |               <el-option label="全部计划" value="all"></el-option> | ||||||
|  |               <el-option label="每日巡检计划" value="daily"></el-option> | ||||||
|  |               <el-option label="每周巡检计划" value="weekly"></el-option> | ||||||
|  |               <el-option label="每月巡检计划" value="monthly"></el-option> | ||||||
|  |               <el-option label="每季度巡检计划" value="quarterly"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="executor" placeholder="执行人"> | ||||||
|  |               <el-option label="全部人员" value="all"></el-option> | ||||||
|  |               <el-option label="张明" value="zhangming"></el-option> | ||||||
|  |               <el-option label="李华" value="lihua"></el-option> | ||||||
|  |               <el-option label="王强" value="wangqiang"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-actions"> | ||||||
|  |             <el-button type="primary" class="search-btn" @click="handleSearch"> 搜索 </el-button> | ||||||
|  |             <el-button type="primary" icon="el-icon-plus" class="create-btn" @click="handleCreateTask"> 手动创建任务 </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 任务卡片列表 --> | ||||||
|  |       <div class="task-cards"> | ||||||
|  |         <div class="task-card" v-for="(task, index) in pagedTasks" :key="index" :class="task.leftLineClass"> | ||||||
|  |           <!-- 顶部信息区域 --> | ||||||
|  |           <div class="task-header"> | ||||||
|  |             <div class="task-title"> | ||||||
|  |               {{ task.title }} | ||||||
|  |             </div> | ||||||
|  |             <div class="task-type-tag" :class="getFaultTypeClass(task.faultType)"> | ||||||
|  |               {{ task.faultType }} | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 滚动内容容器 --> | ||||||
|  |           <div class="task-content-scroll"> | ||||||
|  |             <div class="task-details"> | ||||||
|  |               <div class="detail-item"> | ||||||
|  |                 <span class="detail-label">报修时间</span> | ||||||
|  |                 <span class="detail-value">{{ task.reportTime }}</span> | ||||||
|  |               </div> | ||||||
|  |               <div class="detail-item"> | ||||||
|  |                 <span class="detail-label">报修人</span> | ||||||
|  |                 <span class="detail-value">{{ task.reporter }}</span> | ||||||
|  |               </div> | ||||||
|  |               <div class="detail-item"> | ||||||
|  |                 <span class="detail-label">维修人</span> | ||||||
|  |                 <span class="detail-value">{{ task.maintainer }}</span> | ||||||
|  |               </div> | ||||||
|  |               <div class="detail-item"> | ||||||
|  |                 <span class="detail-label">预计完成</span> | ||||||
|  |                 <span class="detail-value">{{ task.expectedCompleteTime }}</span> | ||||||
|  |               </div> | ||||||
|  |               <div class="detail-item"> | ||||||
|  |                 <span class="detail-label">状态</span> | ||||||
|  |                 <span class="detail-value">{{ task.statusText }}</span> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 已完成状态的额外信息 --> | ||||||
|  |               <div v-if="task.status === 'completed'" class="task-result"> | ||||||
|  |                 <span class="detail-label">完成时间</span> | ||||||
|  |                 <span class="detail-value">{{ task.completeTime }}</span> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 执行中状态的额外信息 --> | ||||||
|  |               <div v-if="task.status === 'executing'" class="detail-item"> | ||||||
|  |                 <span class="detail-label">开始时间</span> | ||||||
|  |                 <span class="detail-value">{{ task.startTime || '30分钟前' }}</span> | ||||||
|  |               </div> | ||||||
|  |               <div v-if="task.status === 'executing'" class="detail-item"> | ||||||
|  |                 <span class="detail-label">进度</span> | ||||||
|  |                 <span class="detail-value">{{ task.progress || '60%' }}</span> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <div class="task-actions"> | ||||||
|  |             <el-button type="text" class="action-btn view-btn" @click="handleView(task)"> 详情 </el-button> | ||||||
|  |             <el-button type="primary" :class="task.actionClass" @click="handleAction(task)"> | ||||||
|  |               {{ task.actionText }} | ||||||
|  |             </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[8, 12, 16, 20]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 新建紧急抢修任务弹窗 --> | ||||||
|  |       <el-dialog | ||||||
|  |         v-model="createTaskDialogVisible" | ||||||
|  |         title="创建紧急抢修任务" | ||||||
|  |         width="800px" | ||||||
|  |         :before-close="handleCancelCreateTask" | ||||||
|  |         custom-class="beautiful-dialog" | ||||||
|  |         center | ||||||
|  |       > | ||||||
|  |         <el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="100px" class="elegant-form"> | ||||||
|  |           <el-form-item label="抢修名称*" prop="repairName"> | ||||||
|  |             <el-input v-model="createTaskForm.repairName" placeholder="简要描述抢修内容" /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-row :gutter="16"> | ||||||
|  |             <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="software" /> | ||||||
|  |                   <el-option label="网络故障" value="network" /> | ||||||
|  |                   <el-option label="环境问题" value="environment" /> | ||||||
|  |                 </el-select> | ||||||
|  |               </el-form-item> | ||||||
|  |             </el-col> | ||||||
|  |             <el-col :span="12"> | ||||||
|  |               <el-form-item label="紧急程度*" prop="priority"> | ||||||
|  |                 <el-select v-model="createTaskForm.priority" placeholder="请选择紧急程度"> | ||||||
|  |                   <el-option label="致命" value="fatal" /> | ||||||
|  |                   <el-option label="紧急" value="urgent" /> | ||||||
|  |                   <el-option label="较危险" value="dangerous" /> | ||||||
|  |                   <el-option label="一般" value="normal" /> | ||||||
|  |                 </el-select> | ||||||
|  |               </el-form-item> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |  | ||||||
|  |           <el-form-item label="故障描述*" prop="detailedDescription"> | ||||||
|  |             <el-input | ||||||
|  |               v-model="createTaskForm.detailedDescription" | ||||||
|  |               type="textarea" | ||||||
|  |               :rows="4" | ||||||
|  |               placeholder="详细描述故障现象、影响范围、潜在威胁等信息" | ||||||
|  |             /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="故障位置*" prop="faultLocation"> | ||||||
|  |             <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> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-row :gutter="16"> | ||||||
|  |             <el-col :span="12"> | ||||||
|  |               <el-form-item label="联系人*" prop="contactPerson"> | ||||||
|  |                 <el-input v-model="createTaskForm.contactPerson" placeholder="您的姓名" /> | ||||||
|  |               </el-form-item> | ||||||
|  |             </el-col> | ||||||
|  |             <el-col :span="12"> | ||||||
|  |               <el-form-item label="联系电话*" prop="contactPhone"> | ||||||
|  |                 <el-input v-model="createTaskForm.contactPhone" placeholder="您的联系电话" /> | ||||||
|  |               </el-form-item> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |  | ||||||
|  |           <el-form-item label="是否需要立即现场支持*"> | ||||||
|  |             <div> | ||||||
|  |               <el-radio v-model="createTaskForm.needSupport" label="yes">是,需要立即派人现场</el-radio> | ||||||
|  |               <el-radio v-model="createTaskForm.needSupport" label="no">否,可远程指导或延后处理</el-radio> | ||||||
|  |             </div> | ||||||
|  |           </el-form-item> | ||||||
|  |         </el-form> | ||||||
|  |  | ||||||
|  |         <template #footer> | ||||||
|  |           <span class="dialog-footer"> | ||||||
|  |             <el-button @click="handleCancelCreateTask">取消</el-button> | ||||||
|  |             <el-button type="primary" @click="handleSaveTask">提交抢修计划</el-button> | ||||||
|  |           </span> | ||||||
|  |         </template> | ||||||
|  |       </el-dialog> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 激活的选项卡 | ||||||
|  | const activeTab = ref('task'); | ||||||
|  |  | ||||||
|  | // 根据故障类型获取对应的CSS类 | ||||||
|  | const getFaultTypeClass = (faultType) => { | ||||||
|  |   const typeMap = { | ||||||
|  |     '电力故障': 'electric', | ||||||
|  |     '设备故障': 'equipment', | ||||||
|  |     '供水问题': 'water', | ||||||
|  |     '设备损坏': 'damage', | ||||||
|  |     '网络中断': 'network', | ||||||
|  |     '制冷系统故障': 'cooling', | ||||||
|  |     '安全问题': 'safety' | ||||||
|  |   }; | ||||||
|  |   return typeMap[faultType] || ''; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const repairType = ref('all'); | ||||||
|  | const taskStatus = ref('all'); | ||||||
|  | const emergencyLevel = ref('all'); | ||||||
|  | const planType = ref('all'); | ||||||
|  | const executor = ref('all'); | ||||||
|  |  | ||||||
|  | // 任务数据 - 使用leftLineClass控制左侧状态线,统一按钮样式 | ||||||
|  | const tasks = ref([ | ||||||
|  |   { | ||||||
|  |     title: '主配电室短路故障', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '抢修中', | ||||||
|  |     leftLineClass: 'left-line-high', // 致命级-红色左侧线 | ||||||
|  |     priority: '致命', | ||||||
|  |     reportTime: '10分钟前', | ||||||
|  |     reporter: '李阳', | ||||||
|  |     maintainer: '张明', | ||||||
|  |     expectedCompleteTime: '30分钟内', | ||||||
|  |     faultType: '电力故障', | ||||||
|  |     faultLocation: '地下一层主配电室', | ||||||
|  |     startTime: '10分钟前', | ||||||
|  |     progress: '40%', | ||||||
|  |     remarks: '已切断该区域电源,正在排查短路点', | ||||||
|  |     actionText: '实时跟进', | ||||||
|  |     actionClass: 'follow-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '三楼卫生间漏水', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '抢修中', | ||||||
|  |     leftLineClass: 'left-line-medium', // 紧急级-黄色左侧线 | ||||||
|  |     priority: '紧急', | ||||||
|  |     reportTime: '45分钟前', | ||||||
|  |     reporter: '李阳', | ||||||
|  |     maintainer: '张明', | ||||||
|  |     expectedCompleteTime: '1小时内', | ||||||
|  |     faultType: '供水问题', | ||||||
|  |     faultLocation: '三楼东侧卫生间', | ||||||
|  |     startTime: '40分钟前', | ||||||
|  |     progress: '70%', | ||||||
|  |     remarks: '已找到漏水点,正在进行修复', | ||||||
|  |     actionText: '实时跟进', | ||||||
|  |     actionClass: 'follow-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '网络主干交换机故障', | ||||||
|  |     status: 'completed', | ||||||
|  |     statusText: '已完成', | ||||||
|  |     leftLineClass: 'left-line-completed', // 已完成-绿色左侧线 | ||||||
|  |     priority: '较危险', | ||||||
|  |     reportTime: '1小时前', | ||||||
|  |     reporter: '李阳', | ||||||
|  |     maintainer: '张明', | ||||||
|  |     expectedCompleteTime: '1小时内', | ||||||
|  |     faultType: '网络中断', | ||||||
|  |     faultLocation: '二楼机房', | ||||||
|  |     completeTime: '2小时前', | ||||||
|  |     remarks: '交换机电源模块故障,已更换备用模块', | ||||||
|  |     actionText: '查看报告', | ||||||
|  |     actionClass: 'evaluate-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '安全出口指示牌损坏', | ||||||
|  |     status: 'pending', | ||||||
|  |     statusText: '待处理', | ||||||
|  |     leftLineClass: 'left-line-medium', // 较危险级-黄色左侧线 | ||||||
|  |     priority: '较危险', | ||||||
|  |     reportTime: '3小时前', | ||||||
|  |     reporter: '李阳', | ||||||
|  |     maintainer: '未分配', | ||||||
|  |     expectedCompleteTime: '今天以内', | ||||||
|  |     faultType: '设备损坏', | ||||||
|  |     faultLocation: '一楼东侧安全通道', | ||||||
|  |     remarks: '指示牌不亮,可能是线路问题', | ||||||
|  |     actionText: '分配任务', | ||||||
|  |     actionClass: 'assign-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '制冷系统主压缩机故障', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '抢修中', | ||||||
|  |     leftLineClass: 'left-line-high', // 致命级-红色左侧线 | ||||||
|  |     priority: '致命', | ||||||
|  |     reportTime: '1小时前', | ||||||
|  |     reporter: '李阳', | ||||||
|  |     maintainer: '张明', | ||||||
|  |     expectedCompleteTime: '45分钟内', | ||||||
|  |     faultType: '制冷系统故障', | ||||||
|  |     faultLocation: '楼顶制冷机房', | ||||||
|  |     startTime: '50分钟前', | ||||||
|  |     progress: '30%', | ||||||
|  |     remarks: '压缩机无法启动,正在检查电路和 refrigerant 压力', | ||||||
|  |     actionText: '实时跟进', | ||||||
|  |     actionClass: 'follow-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '地下室水泵压力不足', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '抢修中', | ||||||
|  |     leftLineClass: 'left-line-medium', // 紧急级-黄色左侧线 | ||||||
|  |     priority: '紧急', | ||||||
|  |     reportTime: '45分钟前', | ||||||
|  |     reporter: '李阳', | ||||||
|  |     maintainer: '张明', | ||||||
|  |     expectedCompleteTime: '1小时内', | ||||||
|  |     faultType: '供水问题', | ||||||
|  |     faultLocation: '地下室水泵房', | ||||||
|  |     startTime: '40分钟前', | ||||||
|  |     progress: '60%', | ||||||
|  |     remarks: '水泵压力不足,正在更换滤网和检查管道', | ||||||
|  |     actionText: '实时跟进', | ||||||
|  |     actionClass: 'follow-btn' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 分页相关 | ||||||
|  | const currentPage = ref(1); | ||||||
|  | const pageSize = ref(8); | ||||||
|  | const total = ref(tasks.value.length); | ||||||
|  |  | ||||||
|  | // 状态排序映射 | ||||||
|  | const statusOrder = { | ||||||
|  |   pending: 0, // 待处理 | ||||||
|  |   executing: 1, // 处理中 | ||||||
|  |   completed: 2 // 已完成 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页处理后的数据(含排序) | ||||||
|  | const pagedTasks = computed(() => { | ||||||
|  |   // 先按状态排序 | ||||||
|  |   const sortedTasks = [...tasks.value].sort((a, b) => { | ||||||
|  |     return statusOrder[a.status] - statusOrder[b.status]; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   // 再进行分页 | ||||||
|  |   const startIndex = (currentPage.value - 1) * pageSize.value; | ||||||
|  |   const endIndex = startIndex + pageSize.value; | ||||||
|  |   return sortedTasks.slice(startIndex, endIndex); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 搜索处理 | ||||||
|  | const handleSearch = () => { | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  |   // 实际应用中这里会根据筛选条件过滤数据 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建紧急抢修任务弹窗相关 | ||||||
|  | const createTaskDialogVisible = ref(false); | ||||||
|  | const createTaskForm = ref({ | ||||||
|  |   repairName: '', | ||||||
|  |   repairType: '', | ||||||
|  |   priority: '', | ||||||
|  |   detailedDescription: '', | ||||||
|  |   faultLocation: '', | ||||||
|  |   contactPerson: '', | ||||||
|  |   contactPhone: '', | ||||||
|  |   needSupport: 'yes' | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | const createTaskRules = { | ||||||
|  |   repairName: [{ required: true, message: '请输入抢修名称', trigger: 'blur' }], | ||||||
|  |   repairType: [{ required: true, message: '请选择抢修类型', trigger: 'change' }], | ||||||
|  |   priority: [{ required: true, message: '请选择紧急程度', trigger: 'change' }], | ||||||
|  |   detailedDescription: [{ required: true, message: '请输入故障描述', trigger: 'blur' }], | ||||||
|  |   faultLocation: [{ required: true, message: '请输入故障位置', trigger: 'blur' }], | ||||||
|  |   contactPerson: [{ required: true, message: '请输入联系人', trigger: 'blur' }], | ||||||
|  |   contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }] | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建任务 | ||||||
|  | const handleCreateTask = () => { | ||||||
|  |   createTaskDialogVisible.value = true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 提交抢修计划 | ||||||
|  | const handleSaveTask = () => { | ||||||
|  |   // 模拟提交抢修计划逻辑 | ||||||
|  |   console.log('提交抢修计划:', createTaskForm.value); | ||||||
|  |   // 关闭弹窗 | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     repairName: '', | ||||||
|  |     repairType: '', | ||||||
|  |     priority: '', | ||||||
|  |     detailedDescription: '', | ||||||
|  |     faultLocation: '', | ||||||
|  |     contactPerson: '', | ||||||
|  |     contactPhone: '', | ||||||
|  |     needSupport: 'yes' | ||||||
|  |   }; | ||||||
|  |   // 这里可以添加成功提示和刷新任务列表的逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 取消创建紧急抢修任务 | ||||||
|  | const handleCancelCreateTask = () => { | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     repairName: '', | ||||||
|  |     repairType: '', | ||||||
|  |     priority: '', | ||||||
|  |     detailedDescription: '', | ||||||
|  |     faultLocation: '', | ||||||
|  |     contactPerson: '', | ||||||
|  |     contactPhone: '', | ||||||
|  |     needSupport: 'yes' | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页事件 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 查看任务详情 | ||||||
|  | const handleView = (task) => { | ||||||
|  |   console.log('查看任务详情:', task); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 处理选项卡点击 | ||||||
|  | const handleTabClick = () => { | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/qiangxiujilu'); | ||||||
|  | }; | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .inspection-tasks { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-cards { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); | ||||||
|  |   gap: 20px; | ||||||
|  |   margin-bottom: 30px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 16px; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   position: relative; | ||||||
|  |   overflow: hidden; | ||||||
|  |   min-height: 300px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 左侧状态线样式 - 与报修管理页面保持一致 */ | ||||||
|  | .task-card::before { | ||||||
|  |   content: ''; | ||||||
|  |   position: absolute; | ||||||
|  |   left: 0; | ||||||
|  |   top: 0; | ||||||
|  |   bottom: 0; | ||||||
|  |   width: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .left-line-high::before { | ||||||
|  |   background-color: #ff4d4f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .left-line-medium::before { | ||||||
|  |   background-color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .left-line-low::before { | ||||||
|  |   background-color: #1677ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .left-line-completed::before { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 滚动内容容器 */ | ||||||
|  | .task-content-scroll { | ||||||
|  |   flex: 1; | ||||||
|  |   overflow-y: auto; | ||||||
|  |   padding-right: 8px; /* 为滚动条预留空间 */ | ||||||
|  |   margin-bottom: 10px; | ||||||
|  |   max-height: 180px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-content-scroll::-webkit-scrollbar { | ||||||
|  |   width: 6px; | ||||||
|  |   height: 6px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-content-scroll::-webkit-scrollbar-track { | ||||||
|  |   background: #f5f7fa; | ||||||
|  |   border-radius: 3px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-content-scroll::-webkit-scrollbar-thumb { | ||||||
|  |   background: #c0c4cc; | ||||||
|  |   border-radius: 3px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-content-scroll::-webkit-scrollbar-thumb:hover { | ||||||
|  |   background: #909399; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-header { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   padding-bottom: 12px; | ||||||
|  |   border-bottom: 1px solid #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-title { | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #1d2129; | ||||||
|  |   line-height: 1.4; | ||||||
|  |   flex: 1; | ||||||
|  |   margin-right: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-type-tag { | ||||||
|  |   padding: 4px 10px; | ||||||
|  |   border-radius: 6px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   border: 1px solid transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 故障类型标签样式 */ | ||||||
|  | .task-type-tag { | ||||||
|  |   background-color: #f6ffed; | ||||||
|  |   color: #52c41a; | ||||||
|  |   border-color: #b7eb8f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-type-tag.electric, | ||||||
|  | .task-type-tag.equipment, | ||||||
|  | .task-type-tag.cooling { | ||||||
|  |   background-color: #fff2f0; | ||||||
|  |   color: #ff4d4f; | ||||||
|  |   border-color: #ffccc7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-type-tag.water, | ||||||
|  | .task-type-tag.damage { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #fa8c16; | ||||||
|  |   border-color: #ffe58f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card:hover { | ||||||
|  |   transform: translateY(-3px); | ||||||
|  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-details { | ||||||
|  |   margin-bottom: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-item { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 8px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   line-height: 1.5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-label { | ||||||
|  |   flex: 0 0 70px; | ||||||
|  |   color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-value { | ||||||
|  |   flex: 1; | ||||||
|  |   color: #4e5969; | ||||||
|  |   word-break: break-all; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-result { | ||||||
|  |   display: flex; | ||||||
|  |   margin: 8px 0; | ||||||
|  |   font-size: 12px; | ||||||
|  |   padding-top: 8px; | ||||||
|  |   border-top: 1px dashed #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-actions { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: flex-end; | ||||||
|  |   align-items: center; | ||||||
|  |   padding-top: 12px; | ||||||
|  |   border-top: 1px solid #f0f2f5; | ||||||
|  |   position: absolute; | ||||||
|  |   bottom: 16px; | ||||||
|  |   right: 16px; | ||||||
|  |   left: 16px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 12px 0 0 0; | ||||||
|  |   z-index: 10; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统一按钮样式 - 与报修管理页面保持一致 */ | ||||||
|  | .action-btn { | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding: 4px 10px; | ||||||
|  |   border-radius: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .view-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .view-btn:hover { | ||||||
|  |   color: #0e42d2; | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .follow-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  |   border-radius: 16px; | ||||||
|  |   padding: 6px 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .follow-btn:hover { | ||||||
|  |   background-color: #0e42d2; | ||||||
|  |   border-color: #0e42d2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .assign-btn { | ||||||
|  |   background-color: #ff7d00; | ||||||
|  |   border-color: #ff7d00; | ||||||
|  |   border-radius: 16px; | ||||||
|  |   padding: 6px 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .assign-btn:hover { | ||||||
|  |   background-color: #e86a00; | ||||||
|  |   border-color: #e86a00; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .evaluate-btn { | ||||||
|  |   background-color: #00b42a; | ||||||
|  |   border-color: #00b42a; | ||||||
|  |   border-radius: 16px; | ||||||
|  |   padding: 6px 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .evaluate-btn:hover { | ||||||
|  |   background-color: #008718; | ||||||
|  |   border-color: #008718; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 其他样式保持不变 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-container { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select { | ||||||
|  |   width: 180px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 12px; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-btn { | ||||||
|  |   background-color: #f2f3f5; | ||||||
|  |   color: #303133; | ||||||
|  |   border-color: #f2f3f5; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-btn:hover { | ||||||
|  |   background-color: #e5e6eb; | ||||||
|  |   border-color: #e5e6eb; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .create-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .create-btn:hover { | ||||||
|  |   background-color: #0e42d2; | ||||||
|  |   border-color: #0e42d2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   margin-top: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 上传图片区域样式 */ | ||||||
|  | .upload-container { | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .upload-box { | ||||||
|  |   border: 2px dashed #dcdfe6; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   padding: 40px 20px; | ||||||
|  |   text-align: center; | ||||||
|  |   cursor: pointer; | ||||||
|  |   background-color: #f8f9fa; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .avatar-uploader-icon { | ||||||
|  |   font-size: 40px; | ||||||
|  |   color: #c0c4cc; | ||||||
|  |   margin-bottom: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .upload-text { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   font-weight: 500; | ||||||
|  |   margin-bottom: 6px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .upload-hint { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #909399; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 弹窗和表单样式 */ | ||||||
|  | .beautiful-dialog { | ||||||
|  |   border-radius: 12px; | ||||||
|  |   overflow: hidden; | ||||||
|  |   box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); | ||||||
|  |   background-color: #fff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .elegant-form .el-form-item { | ||||||
|  |   margin-bottom: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 弹窗按钮样式保持一致 */ | ||||||
|  | .dialog-footer .el-button { | ||||||
|  |   min-width: 80px; | ||||||
|  |   height: 36px; | ||||||
|  |   border-radius: 6px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | ||||||
|  |   margin: 0 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .task-cards { | ||||||
|  |     grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .inspection-tasks { | ||||||
|  |     padding: 16px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-actions { | ||||||
|  |     margin-left: 0; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-bar .el-select { | ||||||
|  |     width: 100%; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .task-cards { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										733
									
								
								src/views/zhinengxunjian/qiangxiujilu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,733 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="inspection-tasks"> | ||||||
|  |       <!-- 导航栏 --> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 页面标题和操作区 --> | ||||||
|  |       <div class="header-section"> | ||||||
|  |         <TitleComponent title="抢修管理模块" subtitle="处理紧急抢修任务,跟踪抢修进度和记录"></TitleComponent> | ||||||
|  |         <div class="header-actions"> | ||||||
|  |           <el-button class="filter-btn" @click="showFilter = !showFilter"> | ||||||
|  |             筛选 | ||||||
|  |             <i class="el-icon-arrow-down ml-1"></i> | ||||||
|  |           </el-button> | ||||||
|  |           <el-button type="primary" class="export-btn" @click="handleExport"> 导出数据 </el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">抢修任务</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">抢修记录</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 筛选栏 (默认隐藏) --> | ||||||
|  |       <div class="filter-bar" v-if="showFilter"> | ||||||
|  |         <div class="filter-container"> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="taskStatus" placeholder="任务状态"> | ||||||
|  |               <el-option label="待执行" value="pending"></el-option> | ||||||
|  |               <el-option label="处理中" value="processing"></el-option> | ||||||
|  |               <el-option label="已完成" value="completed"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="priority" placeholder="紧急程度"> | ||||||
|  |               <el-option label="紧急" value="urgent"></el-option> | ||||||
|  |               <el-option label="常规" value="normal"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="executor" placeholder="抢修人员"> | ||||||
|  |               <el-option label="全部人员" value="all"></el-option> | ||||||
|  |               <el-option label="李明" value="liming"></el-option> | ||||||
|  |               <el-option label="王伟" value="wangwei"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-date-picker | ||||||
|  |               v-model="dateRange" | ||||||
|  |               type="datetimerange" | ||||||
|  |               start-placeholder="开始时间" | ||||||
|  |               end-placeholder="结束时间" | ||||||
|  |               format="YYYY-MM-DD HH:mm" | ||||||
|  |               value-format="YYYY-MM-DD HH:mm" | ||||||
|  |             /> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-actions"> | ||||||
|  |             <el-button type="primary" class="search-btn" @click="handleSearch"> 搜索 </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 统计卡片区域 --> | ||||||
|  |       <div class="statistics-container"> | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">本月抢修总数</p> | ||||||
|  |             <p class="stat-value">18</p> | ||||||
|  |             <p class="stat-trend up">较上月 +8.7%</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon"> | ||||||
|  |             <img src="@/assets/images/qiangxiu.png" alt="本月抢修总数" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">平均抢修时长</p> | ||||||
|  |             <p class="stat-value">58分钟</p> | ||||||
|  |             <p class="stat-trend down">较上月 -2.5分钟</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon"> | ||||||
|  |             <img src="@/assets/images/qiangxiushijian.png" alt="平均抢修时长" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">待处理抢修</p> | ||||||
|  |             <p class="stat-value">3</p> | ||||||
|  |             <p class="stat-trend warning">需要尽快处理</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon warning"> | ||||||
|  |             <img src="@/assets/images/weiqiangxiu.png" alt="待处理抢修" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="stat-card"> | ||||||
|  |           <div class="stat-info"> | ||||||
|  |             <p class="stat-label">按时完成率</p> | ||||||
|  |             <p class="stat-value">92%</p> | ||||||
|  |             <p class="stat-trend up">较上月 +2.4%</p> | ||||||
|  |           </div> | ||||||
|  |           <div class="stat-icon success"> | ||||||
|  |             <img src="@/assets/images/qiangxiuwancheng.png" alt="按时完成率" class="stat-image" /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 抢修记录表格 --> | ||||||
|  |       <div class="table-container"> | ||||||
|  |         <el-table :data="repairRecords" border style="width: 100%" class="record-table"> | ||||||
|  |           <el-table-column align="center" prop="reportNo" label="抢修单号" min-width="120"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="content" label="抢修内容" min-width="200"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="reporter" label="报修人" min-width="80"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="reportTime" label="报修时间" min-width="140"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="handler" label="抢修人员" min-width="80"></el-table-column> | ||||||
|  |           <el-table-column align="center" prop="priority" label="紧急程度" min-width="80"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <span :class="`priority-tag ${scope.row.priorityClass}`">{{ scope.row.priority }}</span> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |           <el-table-column align="center" prop="status" label="处理状态" min-width="80"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <span :class="`status-tag ${scope.row.statusClass}`">{{ scope.row.status }}</span> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |           <el-table-column align="center" prop="duration" label="处理时长" min-width="80"></el-table-column> | ||||||
|  |           <el-table-column align="center" label="操作" min-width="120"> | ||||||
|  |             <template #default="scope"> | ||||||
|  |               <el-button type="text" class="detail-btn" @click="handleDetail(scope.row)"> 详情 </el-button> | ||||||
|  |               <el-button type="text" :class="scope.row.actionClass" @click="handleAction(scope.row)"> | ||||||
|  |                 {{ scope.row.actionText }} | ||||||
|  |               </el-button> | ||||||
|  |             </template> | ||||||
|  |           </el-table-column> | ||||||
|  |         </el-table> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[10, 20, 30, 50]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const taskStatus = ref(''); | ||||||
|  | const priority = ref(''); | ||||||
|  | const executor = ref(''); | ||||||
|  | const dateRange = ref([]); | ||||||
|  | const showFilter = ref(false); | ||||||
|  |  | ||||||
|  | // 分页相关 | ||||||
|  | const currentPage = ref(3); | ||||||
|  | const pageSize = ref(10); | ||||||
|  | const total = ref(187); | ||||||
|  |  | ||||||
|  | // 抢修记录数据 | ||||||
|  | const repairRecords = ref([ | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-001', | ||||||
|  |     content: '网络主干交换机故障AAAAAA', | ||||||
|  |     reporter: '陈明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李明', | ||||||
|  |     priority: '紧急', | ||||||
|  |     priorityClass: 'urgent', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     duration: '10分钟', | ||||||
|  |     actionText: '详情', | ||||||
|  |     actionClass: 'detail-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-002', | ||||||
|  |     content: '实验室水管爆裂', | ||||||
|  |     reporter: '陈明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李明', | ||||||
|  |     priority: '紧急', | ||||||
|  |     priorityClass: 'urgent', | ||||||
|  |     status: '抢修中', | ||||||
|  |     statusClass: 'processing', | ||||||
|  |     duration: '4分钟', | ||||||
|  |     actionText: '查看', | ||||||
|  |     actionClass: 'follow-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-003', | ||||||
|  |     content: '主配电室线路故障', | ||||||
|  |     reporter: '陈明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李明', | ||||||
|  |     priority: '紧急', | ||||||
|  |     priorityClass: 'urgent', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     duration: '10分钟', | ||||||
|  |     actionText: '详情', | ||||||
|  |     actionClass: 'detail-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-004', | ||||||
|  |     content: '网络主干交换机故障AAAAAA', | ||||||
|  |     reporter: '陈明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李明', | ||||||
|  |     priority: '常规', | ||||||
|  |     priorityClass: 'normal', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     duration: '10分钟', | ||||||
|  |     actionText: '详情', | ||||||
|  |     actionClass: 'detail-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-005', | ||||||
|  |     content: '网络主干交换机故障AAAAAA', | ||||||
|  |     reporter: '陈明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李明', | ||||||
|  |     priority: '紧急', | ||||||
|  |     priorityClass: 'urgent', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     duration: '10分钟', | ||||||
|  |     actionText: '详情', | ||||||
|  |     actionClass: 'detail-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-006', | ||||||
|  |     content: '网络主干交换机故障AAAAAA', | ||||||
|  |     reporter: '陈明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李明', | ||||||
|  |     priority: '紧急', | ||||||
|  |     priorityClass: 'urgent', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     duration: '10分钟', | ||||||
|  |     actionText: '详情', | ||||||
|  |     actionClass: 'detail-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     reportNo: 'R-2025-0620-007', | ||||||
|  |     content: '网络主干交换机故障AAAAAA', | ||||||
|  |     reporter: '陈明', | ||||||
|  |     reportTime: '2025-06-20 08:30', | ||||||
|  |     handler: '李明', | ||||||
|  |     priority: '紧急', | ||||||
|  |     priorityClass: 'urgent', | ||||||
|  |     status: '已完成', | ||||||
|  |     statusClass: 'completed', | ||||||
|  |     duration: '10分钟', | ||||||
|  |     actionText: '详情', | ||||||
|  |     actionClass: 'detail-btn' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 搜索处理 | ||||||
|  | const handleSearch = () => { | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  |   // 实际应用中这里会根据筛选条件过滤数据 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导出数据 | ||||||
|  | const handleExport = () => { | ||||||
|  |   console.log('导出抢修记录数据'); | ||||||
|  |   // 实际应用中添加导出逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页事件 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 查看详情 | ||||||
|  | const handleDetail = (record) => { | ||||||
|  |   console.log('查看详情:', record); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 处理操作 | ||||||
|  | const handleAction = (record) => { | ||||||
|  |   console.log('执行操作:', record.actionText, record); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 选项卡切换 | ||||||
|  | const handleTaskTab = () => { | ||||||
|  |   // 抢修任务选项卡逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleRecordTab = () => { | ||||||
|  |   router.push('/rili/qiangxiujiilu'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导航事件 | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/qiangxiujilu'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .inspection-tasks { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 头部标题和操作区 */ | ||||||
|  | .header-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header-actions { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-btn { | ||||||
|  |   background-color: #fff; | ||||||
|  |   color: #303133; | ||||||
|  |   border-color: #dcdfe6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .export-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px 24px; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-container { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select, | ||||||
|  | .filter-bar .el-date-picker { | ||||||
|  |   width: 180px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select .el-input__inner, | ||||||
|  | .filter-bar .el-date-picker .el-input__inner { | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border-color: #dcdfe6; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select .el-input__inner:focus, | ||||||
|  | .filter-bar .el-date-picker .el-input__inner:focus { | ||||||
|  |   border-color: #165dff; | ||||||
|  |   box-shadow: 0 0 0 2px rgba(22, 93, 255, 0.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 12px; | ||||||
|  |   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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计卡片样式 */ | ||||||
|  | .statistics-container { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); | ||||||
|  |   gap: 20px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-card { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 20px; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   transition: transform 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-card:hover { | ||||||
|  |   transform: translateY(-3px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-info { | ||||||
|  |   flex: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #86909c; | ||||||
|  |   margin: 0 0 8px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #1d2129; | ||||||
|  |   margin: 0 0 4px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend { | ||||||
|  |   font-size: 12px; | ||||||
|  |   margin: 0; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.up { | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.up::before { | ||||||
|  |   content: '↑'; | ||||||
|  |   margin-right: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.down { | ||||||
|  |   color: #ff4d4f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.down::before { | ||||||
|  |   content: '↓'; | ||||||
|  |   margin-right: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-trend.warning { | ||||||
|  |   color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-icon { | ||||||
|  |   width: 55px; | ||||||
|  |   height: 55px; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   background-color: #ffebe6; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-image { | ||||||
|  |   width: 45px; | ||||||
|  |   height: 45px; | ||||||
|  |   object-fit: contain; | ||||||
|  | } | ||||||
|  | .table-container { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-table { | ||||||
|  |   border-collapse: separate; | ||||||
|  |   border-spacing: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-table th { | ||||||
|  |   background-color: #f7f8fa; | ||||||
|  |   color: #4e5969; | ||||||
|  |   font-weight: 500; | ||||||
|  |   font-size: 14px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-table td { | ||||||
|  |   color: #1d2129; | ||||||
|  |   font-size: 14px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag { | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.processing { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #faad14; | ||||||
|  |   border: 1px solid #fff1b8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.completed { | ||||||
|  |   background-color: #f0f9eb; | ||||||
|  |   color: #52c41a; | ||||||
|  |   border: 1px solid #e1f3d8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .priority-tag { | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .priority-tag.urgent { | ||||||
|  |   background-color: #ffebe6; | ||||||
|  |   color: #ff4d4f; | ||||||
|  |   border: 1px solid #ffccc7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .priority-tag.normal { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  |   color: #1890ff; | ||||||
|  |   border: 1px solid #b3d8ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .follow-btn { | ||||||
|  |   color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .pagination-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   margin-top: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination { | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination button, | ||||||
|  | .pagination-controls .el-pagination .el-pager li { | ||||||
|  |   min-width: 36px; | ||||||
|  |   height: 36px; | ||||||
|  |   line-height: 36px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .pagination-controls .el-pagination .el-pager li.active { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   color: #fff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   cursor: pointer; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .statistics-container { | ||||||
|  |     grid-template-columns: repeat(2, 1fr); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .inspection-tasks { | ||||||
|  |     padding: 16px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .header-section { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |     gap: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .header-actions { | ||||||
|  |     width: 100%; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-actions { | ||||||
|  |     margin-left: 0; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-bar .el-select, | ||||||
|  |   .filter-bar .el-date-picker { | ||||||
|  |     width: 100%; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .statistics-container { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .table-container { | ||||||
|  |     overflow-x: auto; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										979
									
								
								src/views/zhinengxunjian/renyuanzhuangtai.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,979 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="operation-organization"> | ||||||
|  |       <!-- 顶部导航栏 --> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 页面标题 --> | ||||||
|  |       <TitleComponent title="运维组织模块" subtitle="实时监控人员状态、车辆状态和班组状态"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">人员状态</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">车辆状态</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement3">班组状态</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 内容区域 --> | ||||||
|  |       <div class="content-container"> | ||||||
|  |         <!-- 左侧数据概览区域 --> | ||||||
|  |         <div class="sidebar"> | ||||||
|  |           <div class="stats-card"> | ||||||
|  |             <h3 class="stats-title">人员数据总览</h3> | ||||||
|  |             <!-- 使用ECharts饼图替换原有的环形图 --> | ||||||
|  |             <div class="chart-container"> | ||||||
|  |               <div ref="personnelChart" class="personnel-chart"></div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div class="stats-grid"> | ||||||
|  |               <!-- 总人数 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-icon orange"> | ||||||
|  |                   <img src="@/assets/images/renyuan.png" class="stat-icon-img" alt="总人数" /> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="stat-label">总人数</div> | ||||||
|  |                 <div class="stat-value">{{ totalPersonnel }}</div> | ||||||
|  |                 <div class="stat-desc">所有运维人员总数</div> | ||||||
|  |                 <div class="stat-change green">+1</div> | ||||||
|  |               </div> | ||||||
|  |               <!-- 在线可用 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-icon blue"> | ||||||
|  |                   <img src="@/assets/images/zaixian.png" class="stat-icon-img" alt="在线可用" /> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="stat-label">在线可用</div> | ||||||
|  |                 <div class="stat-value">{{ availablePersonnel }}</div> | ||||||
|  |                 <div class="stat-desc">在线可以投入工作的人员</div> | ||||||
|  |                 <div class="stat-change green">+2</div> | ||||||
|  |               </div> | ||||||
|  |               <!-- 工作中 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-icon green"> | ||||||
|  |                   <img src="@/assets/images/gongzuo.png" class="stat-icon-img" alt="工作中" /> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="stat-label">工作中</div> | ||||||
|  |                 <div class="stat-value">{{ workingPersonnel }}</div> | ||||||
|  |                 <div class="stat-desc">工作中人数</div> | ||||||
|  |                 <div class="stat-change orange">1.2单/人</div> | ||||||
|  |               </div> | ||||||
|  |               <!-- 离线/休息 --> | ||||||
|  |               <div class="stat-item"> | ||||||
|  |                 <div class="stat-icon gray"> | ||||||
|  |                   <img src="@/assets/images/lixian.png" class="stat-icon-img" alt="离线休息" /> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="stat-label">离线/休息</div> | ||||||
|  |                 <div class="stat-value">{{ restingPersonnel }}</div> | ||||||
|  |                 <div class="stat-desc">休假人员</div> | ||||||
|  |                 <div class="stat-change gray">休息离线的人员</div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <!-- 右侧人员列表区域,带滚动条 --> | ||||||
|  |         <div class="main-content"> | ||||||
|  |           <div class="scroll-wrapper"> | ||||||
|  |             <!-- 固定的顶部空间,不随内容滚动 --> | ||||||
|  |             <div class="fixed-top-space"></div> | ||||||
|  |             <!-- 可滚动的内容区域 --> | ||||||
|  |             <div class="scrollable-content"> | ||||||
|  |               <div class="scrollable-inner"> | ||||||
|  |                 <div class="personnel-grid"> | ||||||
|  |                   <div v-for="(person, index) in personnelList" :key="index" class="person-card"> | ||||||
|  |                     <div class="person-header"> | ||||||
|  |                       <div class="avatar"> | ||||||
|  |                         <img src="@/assets/images/attendanceperson.png" class="avatar-img" /> | ||||||
|  |                         <div class="status-indicator" :class="person.statusClass"></div> | ||||||
|  |                       </div> | ||||||
|  |                       <div class="person-info"> | ||||||
|  |                         <div class="person-name">{{ person.name }}</div> | ||||||
|  |                         <div class="person-status" :class="person.statusClass">{{ person.statusText }}</div> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="person-details"> | ||||||
|  |                       <div class="detail-row"> | ||||||
|  |                         <div class="detail-item">工号: {{ person.id }}</div> | ||||||
|  |                         <div class="detail-item">岗位: {{ person.position }}</div> | ||||||
|  |                       </div> | ||||||
|  |                       <div class="detail-row"> | ||||||
|  |                         <div class="detail-item">班组: {{ person.team }}</div> | ||||||
|  |                         <div class="detail-item">今日完成: {{ person.completedTasks }}单</div> | ||||||
|  |                       </div> | ||||||
|  |                       <div class="detail-row"> | ||||||
|  |                         <div class="detail-item full-width">当前任务: {{ person.currentTask || '无' }}</div> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="person-actions"> | ||||||
|  |                       <el-button type="text" @click="viewDetails(person)" class="detail-btn">详情</el-button> | ||||||
|  |                       <el-button type="text" @click="assignTask(person)" class="assign-btn"> | ||||||
|  |                         {{ person.statusClass === 'online' ? '派单' : person.statusClass === 'working' ? '联系' : '留言' }} | ||||||
|  |                       </el-button> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, watch, onMounted } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
|  |  | ||||||
|  | // 激活的选项卡 | ||||||
|  | const activeTab = ref('personnel'); | ||||||
|  |  | ||||||
|  | // 统计数据(保持原有数据不变) | ||||||
|  | const totalPersonnel = ref(36); | ||||||
|  | const availablePersonnel = ref(18); | ||||||
|  | const workingPersonnel = ref(12); | ||||||
|  | const restingPersonnel = ref(6); | ||||||
|  | const onlineRate = ref(82); | ||||||
|  |  | ||||||
|  | // 人员状态数据 - 使用原有数据结构 | ||||||
|  | const personnelStatusData = { | ||||||
|  |   '在线可用': availablePersonnel.value, | ||||||
|  |   '离线休息': restingPersonnel.value | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 初始化图表 | ||||||
|  | const personnelChart = ref(null); | ||||||
|  | let chartInstance = null; | ||||||
|  |  | ||||||
|  | // 人员列表数据(保持不变) | ||||||
|  | const personnelList = ref([ | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-001', | ||||||
|  |     name: '张工', | ||||||
|  |     position: '设备维护工程师', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     statusText: '在线可用', | ||||||
|  |     statusClass: 'online', | ||||||
|  |     completedTasks: 2, | ||||||
|  |     currentTask: '', | ||||||
|  |     avatar: 'https://p9-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/937facf77da3466fafaf9ff8f0223333.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-006', | ||||||
|  |     name: '李工', | ||||||
|  |     position: '系统工程师', | ||||||
|  |     team: '第三运维组', | ||||||
|  |     statusText: '工作中', | ||||||
|  |     statusClass: 'working', | ||||||
|  |     completedTasks: 1, | ||||||
|  |     currentTask: 'WO-2023-0619-055', | ||||||
|  |     avatar: 'https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/63a989286b91488ca0c4a0141041ea41.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-015', | ||||||
|  |     name: '刘工', | ||||||
|  |     position: '安全检查工程师', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     statusText: '工作中', | ||||||
|  |     statusClass: 'working', | ||||||
|  |     completedTasks: 0, | ||||||
|  |     currentTask: 'WO-2023-0618-054', | ||||||
|  |     avatar: 'https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/0a6cf54a4a1c4623b8365939c8d61adc.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-022', | ||||||
|  |     name: '孙工', | ||||||
|  |     position: '安装调试工程师', | ||||||
|  |     team: '第三运维组', | ||||||
|  |     statusText: '离线休息', | ||||||
|  |     statusClass: 'offline', | ||||||
|  |     completedTasks: 2, | ||||||
|  |     currentTask: '', | ||||||
|  |     avatar: 'https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/f3e766fffb5d4573945ef7501894c461.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-008', | ||||||
|  |     name: '李工', | ||||||
|  |     position: '系统工程师', | ||||||
|  |     team: '第三运维组', | ||||||
|  |     statusText: '工作中', | ||||||
|  |     statusClass: 'working', | ||||||
|  |     completedTasks: 1, | ||||||
|  |     currentTask: 'WO-2023-0619-055', | ||||||
|  |     avatar: 'https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/d315aa56eb894980bf090804594ccf13.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-016', | ||||||
|  |     name: '刘工', | ||||||
|  |     position: '安全检查工程师', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     statusText: '工作中', | ||||||
|  |     statusClass: 'working', | ||||||
|  |     completedTasks: 0, | ||||||
|  |     currentTask: 'WO-2023-0618-054', | ||||||
|  |     avatar: 'https://p9-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/937facf77da3466fafaf9ff8f0223333.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-002', | ||||||
|  |     name: '张工', | ||||||
|  |     position: '设备维护工程师', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     statusText: '在线可用', | ||||||
|  |     statusClass: 'online', | ||||||
|  |     completedTasks: 2, | ||||||
|  |     currentTask: '', | ||||||
|  |     avatar: 'https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/63a989286b91488ca0c4a0141041ea41.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-009', | ||||||
|  |     name: '李工', | ||||||
|  |     position: '系统工程师', | ||||||
|  |     team: '第三运维组', | ||||||
|  |     statusText: '工作中', | ||||||
|  |     statusClass: 'working', | ||||||
|  |     completedTasks: 1, | ||||||
|  |     currentTask: 'WO-2023-0619-055', | ||||||
|  |     avatar: 'https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/0a6cf54a4a1c4623b8365939c8d61adc.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'EMP-2023-017', | ||||||
|  |     name: '刘工', | ||||||
|  |     position: '安全检查工程师', | ||||||
|  |     team: '第一运维组', | ||||||
|  |     statusText: '工作中', | ||||||
|  |     statusClass: 'working', | ||||||
|  |     completedTasks: 0, | ||||||
|  |     currentTask: 'WO-2023-0618-054', | ||||||
|  |     avatar: 'https://p3-flow-imagex-sign.byteimg.com/tos-cn-i-a9rns2rl98/f3e766fffb5d4573945ef7501894c461.png~tplv-a9rns2rl98-24:720:720.png' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 初始化饼图 | ||||||
|  | const initChart = () => { | ||||||
|  |   if (chartInstance) { | ||||||
|  |     chartInstance.dispose(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   chartInstance = echarts.init(personnelChart.value); | ||||||
|  |  | ||||||
|  |   const names = Object.keys(personnelStatusData); | ||||||
|  |   const values = Object.values(personnelStatusData).map((item) => Number(Number(item).toFixed(2))); | ||||||
|  |   const sumValue = values.reduce((total, num) => total + num, 0); | ||||||
|  |  | ||||||
|  |   // 设置图表配置 - 美化饼图样式,保持原有数据 | ||||||
|  |   const option = { | ||||||
|  |     tooltip: { | ||||||
|  |       trigger: 'item', | ||||||
|  |       formatter: '{b}: {c}人 ({d}%)' | ||||||
|  |     }, | ||||||
|  |     legend: { | ||||||
|  |       show: true, | ||||||
|  |       orient: 'horizontal', | ||||||
|  |       bottom: 10, | ||||||
|  |       itemWidth: 12, | ||||||
|  |       itemHeight: 12, | ||||||
|  |       textStyle: { | ||||||
|  |         color: '#606266', | ||||||
|  |         fontSize: 14 | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     series: [ | ||||||
|  |       // 主饼图 | ||||||
|  |       { | ||||||
|  |         name: '人员状态', | ||||||
|  |         type: 'pie', | ||||||
|  |         radius: ['40%', '70%'], | ||||||
|  |         center: ['50%', '50%'], | ||||||
|  |         avoidLabelOverlap: false, | ||||||
|  |         itemStyle: { | ||||||
|  |           borderRadius: 4, | ||||||
|  |           borderColor: '#fff', | ||||||
|  |           borderWidth: 2, | ||||||
|  |           shadowBlur: 6, | ||||||
|  |           shadowColor: 'rgba(0, 0, 0, 0.1)' | ||||||
|  |         }, | ||||||
|  |         label: { | ||||||
|  |           show: false, | ||||||
|  |           position: 'outside', | ||||||
|  |           formatter: '{d}%', | ||||||
|  |           fontSize: 14, | ||||||
|  |           fontWeight: 'bold', | ||||||
|  |           color: '#303133', | ||||||
|  |           lineHeight: 20 | ||||||
|  |         }, | ||||||
|  |         labelLine: { | ||||||
|  |           show: true, | ||||||
|  |           length: 15, | ||||||
|  |           length2: 10, | ||||||
|  |           lineStyle: { | ||||||
|  |             width: 1 | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         emphasis: { | ||||||
|  |           scale: true, | ||||||
|  |           scaleSize: 15 | ||||||
|  |         }, | ||||||
|  |         data: [ | ||||||
|  |           { | ||||||
|  |             value: availablePersonnel.value, | ||||||
|  |             name: '在线可用人数', | ||||||
|  |             itemStyle: { | ||||||
|  |               color: '#165dff' | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |  | ||||||
|  |           { | ||||||
|  |             value: restingPersonnel.value, | ||||||
|  |             name: '离线休息人数', | ||||||
|  |             itemStyle: { | ||||||
|  |               color: '#40c9c6' | ||||||
|  |             }, | ||||||
|  |             emphasis: { | ||||||
|  |               itemStyle: { | ||||||
|  |                 shadowBlur: 15, | ||||||
|  |                 shadowColor: 'rgba(64, 201, 198, 0.4)' | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   chartInstance.setOption(option); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 监听数据变化,更新图表 | ||||||
|  | watch([availablePersonnel, workingPersonnel, restingPersonnel], () => { | ||||||
|  |   // 更新人员状态数据 | ||||||
|  |   personnelStatusData['在线可用'] = availablePersonnel.value; | ||||||
|  |  | ||||||
|  |   personnelStatusData['离线休息'] = restingPersonnel.value; | ||||||
|  |  | ||||||
|  |   // 重新初始化图表 | ||||||
|  |   initChart(); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 页面加载完成后初始化图表 | ||||||
|  | onMounted(() => { | ||||||
|  |   initChart(); | ||||||
|  |  | ||||||
|  |   // 监听窗口大小变化,调整图表尺寸 | ||||||
|  |   window.addEventListener('resize', () => { | ||||||
|  |     if (chartInstance) { | ||||||
|  |       chartInstance.resize(); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 选项卡点击事件 | ||||||
|  | const handleTabClick = (tab) => { | ||||||
|  |   console.log('切换到选项卡:', tab.name); | ||||||
|  |   if (tab.name === 'vehicles') { | ||||||
|  |     // 加载车辆状态数据 | ||||||
|  |   } else if (tab.name === 'teams') { | ||||||
|  |     // 加载班组状态数据 | ||||||
|  |   } else { | ||||||
|  |     // 加载人员状态数据 | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 人员卡片操作 | ||||||
|  | const viewDetails = (person) => { | ||||||
|  |   console.log('查看详情:', person); | ||||||
|  |   // 跳转到人员详情页 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const assignTask = (person) => { | ||||||
|  |   console.log('指派任务给:', person); | ||||||
|  |   // 打开任务指派对话框 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导航路由跳转 | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/cheliangzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/banzhuzhuangtai'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .operation-organization { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs { | ||||||
|  |   padding-top: 1px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__header { | ||||||
|  |   margin: 0 -20px; | ||||||
|  |   padding: 0 20px; | ||||||
|  |   border-bottom: 1px solid #e4e7ed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__nav-wrap::after { | ||||||
|  |   height: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   padding: 16px 20px; | ||||||
|  |   margin-right: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item.is-active { | ||||||
|  |   color: #165dff; | ||||||
|  |   font-weight: 500; | ||||||
|  |   border-bottom: 2px solid #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .custom-tabs .el-tabs__item:hover { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 内容容器样式 */ | ||||||
|  | .content-container { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 24px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 左侧边栏样式 */ | ||||||
|  | .sidebar { | ||||||
|  |   width: 400px; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stats-card { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 12px; | ||||||
|  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06); | ||||||
|  |   padding: 24px; | ||||||
|  |   height: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stats-title { | ||||||
|  |   font-size: 18px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #2c3e50; | ||||||
|  |   margin: 0 0 24px 0; | ||||||
|  |   padding-bottom: 16px; | ||||||
|  |   border-bottom: 1px solid #f0f0f0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 图表容器 */ | ||||||
|  | .chart-container { | ||||||
|  |   border: 1px solid #f0f0f0; | ||||||
|  |   border-radius: 20%; | ||||||
|  |   margin-bottom: 32px; | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   align-items: center; | ||||||
|  |   padding: 10px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .personnel-chart { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 300px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计网格 */ | ||||||
|  | .stats-grid { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(2, 1fr); | ||||||
|  |   gap: 16px; /* 项之间的间距 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 单个统计项:纵向居中,卡片化 */ | ||||||
|  | .stat-item { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   padding: 16px; | ||||||
|  |   text-align: center; | ||||||
|  |   border: 1px solid #f0f0f0; | ||||||
|  |   box-shadow: 0 2px 6px rgba(0, 0, 0, 0.03); | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 图标容器:圆形背景 + 颜色区分 */ | ||||||
|  | .stat-icon { | ||||||
|  |   width: 40px; | ||||||
|  |   height: 40px; | ||||||
|  |   border-radius: 50%; /* 圆形背景 */ | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: center; | ||||||
|  |   margin-bottom: 8px; | ||||||
|  | } | ||||||
|  | /* 不同图标背景色 */ | ||||||
|  | .stat-icon.orange { | ||||||
|  |   background-color: #fff2e8; | ||||||
|  | } | ||||||
|  | .stat-icon.blue { | ||||||
|  |   background-color: #e6f4ff; | ||||||
|  | } | ||||||
|  | .stat-icon.green { | ||||||
|  |   background-color: #f6ffed; | ||||||
|  | } | ||||||
|  | .stat-icon.gray { | ||||||
|  |   background-color: #f5f5f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 图标尺寸 */ | ||||||
|  | .stat-icon-img { | ||||||
|  |   width: 24px; | ||||||
|  |   height: 24px; | ||||||
|  |   object-fit: contain; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 标题:小字号 + 浅灰色 */ | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #666; | ||||||
|  |   margin-bottom: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 数值:大字号 + 深灰色 + 加粗 */ | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 20px; | ||||||
|  |   font-weight: bold; | ||||||
|  |   color: #333; | ||||||
|  |   margin-bottom: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 描述:更小字号 + 浅灰色 */ | ||||||
|  | .stat-desc { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #999; | ||||||
|  |   margin-bottom: 6px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 变化/额外说明:彩色小字号 */ | ||||||
|  | .stat-change { | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  | .stat-change.green { | ||||||
|  |   color: #00b42a; | ||||||
|  | } /* 绿色(增长) */ | ||||||
|  | .stat-change.orange { | ||||||
|  |   color: #ff7d00; | ||||||
|  | } /* 橙色(效率) */ | ||||||
|  | .stat-change.gray { | ||||||
|  |   color: #999; | ||||||
|  | } /* 灰色(说明) */ | ||||||
|  |  | ||||||
|  | /* 主内容区域 */ | ||||||
|  | .main-content { | ||||||
|  |   flex: 1; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 12px; | ||||||
|  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06); | ||||||
|  |   overflow: hidden; | ||||||
|  |   padding: 0 28px 28px 28px; | ||||||
|  | } | ||||||
|  | /* 滚动包装器 */ | ||||||
|  | .scroll-wrapper { | ||||||
|  |   height: 100%; | ||||||
|  |   position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 固定的顶部空间,不随内容滚动 */ | ||||||
|  | .fixed-top-space { | ||||||
|  |   height: 40px; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 可滚动的内容区域 */ | ||||||
|  | .scrollable-content { | ||||||
|  |   max-height: calc(120vh - 340px - 40px); /* 减去顶部固定空间的高度 */ | ||||||
|  |   overflow: auto; | ||||||
|  |   scrollbar-width: thin; | ||||||
|  |   scrollbar-color: rgba(150, 150, 150, 0.5) transparent; | ||||||
|  | } | ||||||
|  | /* 内容包装器 */ | ||||||
|  | .content-wrapper { | ||||||
|  |   padding: 0 28px 60px 28px; | ||||||
|  | } | ||||||
|  | /* Webkit浏览器自定义滚动条样式 */ | ||||||
|  | .scrollable-content::-webkit-scrollbar { | ||||||
|  |   width: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollable-content::-webkit-scrollbar-track { | ||||||
|  |   background: transparent; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollable-content::-webkit-scrollbar-thumb { | ||||||
|  |   background-color: rgba(150, 150, 150, 0.5); | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border: 2px solid transparent; | ||||||
|  |   background-clip: content-box; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollable-content::-webkit-scrollbar-thumb:hover { | ||||||
|  |   background-color: rgba(150, 150, 150, 0.8); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 增强内容区域标题样式 */ | ||||||
|  | .main-content-title { | ||||||
|  |   font-size: 18px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #2c3e50; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   padding-bottom: 12px; | ||||||
|  |   border-bottom: 2px solid #f0f0f0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 人员网格 */ | ||||||
|  | .personnel-grid { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(3, 1fr); | ||||||
|  |   gap: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-card { | ||||||
|  |   border: 1px solid #f0f0f0; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   padding: 16px; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   background-color: #ffffff; | ||||||
|  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); | ||||||
|  |   min-height: 220px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-card:hover { | ||||||
|  |   box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); | ||||||
|  |   border-color: #e6f7ff; | ||||||
|  |   transform: translateY(-2px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-header { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .avatar { | ||||||
|  |   position: relative; | ||||||
|  |   width: 56px; | ||||||
|  |   height: 56px; | ||||||
|  |   margin-right: 12px; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .avatar-img { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 100%; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   object-fit: cover; | ||||||
|  |   border: 2px solid #f0f0f0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-indicator { | ||||||
|  |   position: absolute; | ||||||
|  |   bottom: 0; | ||||||
|  |   right: 0; | ||||||
|  |   width: 16px; | ||||||
|  |   height: 16px; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   border: 3px solid #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-indicator.online { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-indicator.working { | ||||||
|  |   background-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-indicator.offline { | ||||||
|  |   background-color: #909399; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-info { | ||||||
|  |   flex: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-name { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #2c3e50; | ||||||
|  |   margin-bottom: 4px; | ||||||
|  |   line-height: 1.2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-status { | ||||||
|  |   font-size: 12px; | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   border-radius: 12px; | ||||||
|  |   display: inline-block; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-status.online { | ||||||
|  |   background-color: #cbfad6; | ||||||
|  |   color: #19b949; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-status.working { | ||||||
|  |   background-color: #fff7e6; | ||||||
|  |   color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-status.offline { | ||||||
|  |   background-color: #f5f5f5; | ||||||
|  |   color: #909399; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-details { | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   border-top: none; | ||||||
|  |   padding-top: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-row { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 8px; | ||||||
|  |   border-bottom: 1px dotted #f0f0f0; | ||||||
|  |   padding-bottom: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-row:last-child { | ||||||
|  |   margin-bottom: 0; | ||||||
|  |   border-bottom: none; | ||||||
|  |   padding-bottom: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-item { | ||||||
|  |   font-size: 13px; | ||||||
|  |   color: #606266; | ||||||
|  |   line-height: 1.6; | ||||||
|  |   flex: 1; | ||||||
|  |   padding: 0 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-item:first-child { | ||||||
|  |   padding-left: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-item:last-child { | ||||||
|  |   padding-right: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-item.full-width { | ||||||
|  |   flex: 1 0 100%; | ||||||
|  |   padding: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .person-actions { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: flex-end; | ||||||
|  |   gap: 12px; | ||||||
|  |   border-top: 1px solid #f0f0f0; | ||||||
|  |   padding-top: 16px; | ||||||
|  |   margin-top: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 美化按钮样式 */ | ||||||
|  | .detail-btn, | ||||||
|  | .assign-btn { | ||||||
|  |   display: inline-flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: center; | ||||||
|  |   padding: 6px 16px; | ||||||
|  |   border-radius: 16px; | ||||||
|  |   font-size: 13px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border: 1px solid transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-btn { | ||||||
|  |   color: #165dff; | ||||||
|  |   background-color: #f0f7ff; | ||||||
|  |   border-color: #d6e4ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-btn:hover { | ||||||
|  |   color: #094ab2; | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  |   border-color: #91bfff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .assign-btn { | ||||||
|  |   color: #fa8c16; | ||||||
|  |   background-color: #fff9f0; | ||||||
|  |   border-color: #ffe7ba; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .assign-btn:hover { | ||||||
|  |   color: #e67700; | ||||||
|  |   background-color: #fff7e6; | ||||||
|  |   border-color: #ffd591; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 12px; | ||||||
|  |   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); | ||||||
|  |   padding: 4px; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 14px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  |   position: relative; | ||||||
|  |   z-index: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #165dff; | ||||||
|  |   background-color: #f0f7ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background: linear-gradient(135deg, #165dff 0%, #4080ff 100%); | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 4px 12px rgba(22, 93, 255, 0.3); | ||||||
|  |   border-right-color: transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active:hover { | ||||||
|  |   background: linear-gradient(135deg, #094ab2 0%, #3366cc 100%); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   cursor: pointer; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 滚动条样式 */ | ||||||
|  | .scrollable-content::-webkit-scrollbar { | ||||||
|  |   width: 6px; | ||||||
|  |   height: 6px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollable-content::-webkit-scrollbar-track { | ||||||
|  |   background: #f5f7fa; | ||||||
|  |   border-radius: 3px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollable-content::-webkit-scrollbar-thumb { | ||||||
|  |   background: #c0c4cc; | ||||||
|  |   border-radius: 3px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollable-content::-webkit-scrollbar-thumb:hover { | ||||||
|  |   background: #909399; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .content-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .sidebar { | ||||||
|  |     width: 100%; | ||||||
|  |     margin-bottom: 24px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .scrollable-content { | ||||||
|  |     max-height: 600px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .operation-organization { | ||||||
|  |     padding: 10px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .navigation-tabs { | ||||||
|  |     flex-wrap: wrap; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .nav-tab { | ||||||
|  |     flex: 1 0 33%; | ||||||
|  |     padding: 10px 0; | ||||||
|  |     font-size: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .personnel-grid { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .personnel-chart { | ||||||
|  |     height: 250px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										1588
									
								
								src/views/zhinengxunjian/shiyanguanli.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										969
									
								
								src/views/zhinengxunjian/shiyanjilu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,969 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="operation-inspection"> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <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> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡和按钮组合 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">实验计划</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">实验任务</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement3">实验记录</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 4. 筛选和操作区域 --> | ||||||
|  |       <div class="filter-and-actions"> | ||||||
|  |         <div class="filters"> | ||||||
|  |           <el-select v-model="filterStatus" placeholder="巡检状态" clearable> | ||||||
|  |             <el-option label="全部状态" value="all"></el-option> | ||||||
|  |             <el-option label="正常" value="normal"></el-option> | ||||||
|  |             <el-option label="需关注" value="attention"></el-option> | ||||||
|  |             <el-option label="有问题" value="problem"></el-option> | ||||||
|  |           </el-select> | ||||||
|  |  | ||||||
|  |           <el-select v-model="filterType" placeholder="巡检类型" clearable> | ||||||
|  |             <el-option label="全部类型" value="all"></el-option> | ||||||
|  |             <el-option label="数据库" value="database"></el-option> | ||||||
|  |             <el-option label="服务器" value="server"></el-option> | ||||||
|  |             <el-option label="网络设备" value="network"></el-option> | ||||||
|  |           </el-select> | ||||||
|  |  | ||||||
|  |           <el-date-picker | ||||||
|  |             v-model="dateRange" | ||||||
|  |             type="daterange" | ||||||
|  |             range-separator="至" | ||||||
|  |             start-placeholder="开始日期" | ||||||
|  |             end-placeholder="结束日期" | ||||||
|  |             value-format="YYYY-MM-DD" | ||||||
|  |             class="date-picker" | ||||||
|  |           ></el-date-picker> | ||||||
|  |  | ||||||
|  |           <el-button type="primary" class="search-btn"> 搜索 </el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 5. 主内容区 --> | ||||||
|  |       <div class="content-container"> | ||||||
|  |         <!-- 5.3 巡检记录(根据图片调整) --> | ||||||
|  |         <div v-if="activeTab === 'record'" class="record-container"> | ||||||
|  |           <h2 class="section-title">试验记录与报告</h2> | ||||||
|  |           <p class="section-subtitle">截止至 {{ currentDate }}</p> | ||||||
|  |  | ||||||
|  |           <!-- 统计卡片 --> | ||||||
|  |           <div class="stat-grid"> | ||||||
|  |             <div class="stat-card"> | ||||||
|  |               <p class="stat-label">本月完成试验</p> | ||||||
|  |               <p class="stat-value">{{ statData.completed }}<span class="stat-change up">较上月 ↑2.4%</span></p> | ||||||
|  |             </div> | ||||||
|  |             <div class="stat-card"> | ||||||
|  |               <p class="stat-label">试验通过率</p> | ||||||
|  |               <p class="stat-value">{{ statData.passRate }}%<span class="stat-change up">较上月 ↑5.6%</span></p> | ||||||
|  |             </div> | ||||||
|  |             <div class="stat-card"> | ||||||
|  |               <p class="stat-label">待分析记录</p> | ||||||
|  |               <p class="stat-value">{{ statData.pendingAnalysis }}<span class="stat-change warning">需要及时处理</span></p> | ||||||
|  |             </div> | ||||||
|  |             <div class="stat-card"> | ||||||
|  |               <p class="stat-label">平均试验时长</p> | ||||||
|  |               <p class="stat-value">{{ statData.avgDuration }}<span class="stat-change down">较上月 ↓9.4分钟</span></p> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 试验记录列表 --> | ||||||
|  |           <div class="test-records"> | ||||||
|  |             <!-- 数据库性能巡检记录 --> | ||||||
|  |             <div class="test-record-card passed"> | ||||||
|  |               <div class="record-header"> | ||||||
|  |                 <h3 class="record-title">数据库性能巡检</h3> | ||||||
|  |                 <p class="record-date"> | ||||||
|  |                   {{ testRecords[0].date }} <span class="record-time">耗时: {{ testRecords[0].duration }}</span> | ||||||
|  |                 </p> | ||||||
|  |                 <span class="status-tag status-passed">通过</span> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 试验进度 --> | ||||||
|  |               <div class="test-progress"> | ||||||
|  |                 <div class="progress-step active"> | ||||||
|  |                   <div class="step-number">1</div> | ||||||
|  |                   <div class="step-name">准备环境</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="progress-line active"></div> | ||||||
|  |                 <div class="progress-step active"> | ||||||
|  |                   <div class="step-number">2</div> | ||||||
|  |                   <div class="step-name">50%负载</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="progress-line active"></div> | ||||||
|  |                 <div class="progress-step active"> | ||||||
|  |                   <div class="step-number">3</div> | ||||||
|  |                   <div class="step-name">80%负载</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="progress-line active"></div> | ||||||
|  |                 <div class="progress-step active"> | ||||||
|  |                   <div class="step-number">4</div> | ||||||
|  |                   <div class="step-name">100%负载</div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 试验结果 --> | ||||||
|  |               <div class="test-result"> | ||||||
|  |                 <h4 class="result-title">试验结果</h4> | ||||||
|  |                 <p class="result-content">系统在100%负载下稳定运行1小时,CPU平均使用率92%,内存使用率88%,无崩溃或异常重启现象。</p> | ||||||
|  |                 <p class="result-details"> | ||||||
|  |                   平均响应时间: {{ testRecords[0].responseTime }} | 错误率: {{ testRecords[0].errorRate }} | 温度值: {{ testRecords[0].temperature }} | ||||||
|  |                 </p> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <div class="record-actions"> | ||||||
|  |                 <button class="operate-btn view-btn">查看详情</button> | ||||||
|  |                 <button class="operate-btn report-btn">生成报告</button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <!-- 1000用户并发测试记录 --> | ||||||
|  |             <div class="test-record-card failed"> | ||||||
|  |               <div class="record-header"> | ||||||
|  |                 <h3 class="record-title">1000用户并发测试</h3> | ||||||
|  |                 <p class="record-date"> | ||||||
|  |                   {{ testRecords[1].date }} <span class="record-time">耗时: {{ testRecords[1].duration }}</span> | ||||||
|  |                 </p> | ||||||
|  |                 <span class="status-tag status-failed">失败</span> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 试验进度 --> | ||||||
|  |               <div class="test-progress"> | ||||||
|  |                 <div class="progress-step active"> | ||||||
|  |                   <div class="step-number">1</div> | ||||||
|  |                   <div class="step-name">准备环境</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="progress-line active"></div> | ||||||
|  |                 <div class="progress-step active"> | ||||||
|  |                   <div class="step-number">2</div> | ||||||
|  |                   <div class="step-name">300用户</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="progress-line active"></div> | ||||||
|  |                 <div class="progress-step active"> | ||||||
|  |                   <div class="step-number">3</div> | ||||||
|  |                   <div class="step-name">500用户</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="progress-line failed"></div> | ||||||
|  |                 <div class="progress-step failed"> | ||||||
|  |                   <div class="step-number">4</div> | ||||||
|  |                   <div class="step-name">800用户</div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 失败原因分析 --> | ||||||
|  |               <div class="test-result failure-analysis"> | ||||||
|  |                 <h4 class="result-title">失败原因分析</h4> | ||||||
|  |                 <p class="result-content">当并发用户数达到780人时,数据库连接耗尽,新用户无法建立数据库连接,导致系统响应超时。</p> | ||||||
|  |  | ||||||
|  |                 <!-- 改进建议 --> | ||||||
|  |                 <div class="improvement-suggestion"> | ||||||
|  |                   <i class="fas fa-lightbulb"></i> | ||||||
|  |                   <p>建议: 增加数据库连接池最大连接数,优化长连接超时时间,增加连接复用机制分析评估。</p> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <div class="record-actions"> | ||||||
|  |                 <button class="operate-btn view-btn">查看详情</button> | ||||||
|  |                 <button class="operate-btn report-btn">生成报告</button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <!-- 5.1 巡检计划表格 --> | ||||||
|  |         <div v-if="activeTab === 'plan'" class="table-container"> | ||||||
|  |           <el-table :data="planTableData" border> | ||||||
|  |             <el-table-column prop="name" label="计划名称" width="220"> | ||||||
|  |               <template #default="scope"> | ||||||
|  |                 <div class="plan-name">{{ scope.row.name }}</div> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |             <el-table-column prop="type" label="巡检类型" width="120"></el-table-column> | ||||||
|  |             <el-table-column prop="cycle" label="巡检周期" width="120"></el-table-column> | ||||||
|  |             <el-table-column prop="dateRange" label="执行时间范围"></el-table-column> | ||||||
|  |             <el-table-column prop="progress" label="完成进度" width="120"> | ||||||
|  |               <template #default="scope"> | ||||||
|  |                 <div class="progress-bar"> | ||||||
|  |                   <div class="progress-fill" :style="{ width: scope.row.progress + '%', backgroundColor: getProgressColor(scope.row.status) }"></div> | ||||||
|  |                 </div> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |             <el-table-column prop="status" label="状态" width="100"> | ||||||
|  |               <template #default="scope"> | ||||||
|  |                 <span :class="['status-tag', `status-${scope.row.status}`]"> | ||||||
|  |                   {{ getStatusText(scope.row.status) }} | ||||||
|  |                 </span> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |             <el-table-column prop="responsible" label="负责人" width="120"></el-table-column> | ||||||
|  |             <el-table-column label="操作" width="220"> | ||||||
|  |               <template #default="scope"> | ||||||
|  |                 <div class="operation-buttons"> | ||||||
|  |                   <button class="operate-btn edit-btn" v-if="['drafted', 'paused'].includes(scope.row.status)">编辑</button> | ||||||
|  |                   <button class="operate-btn execute-btn" v-if="scope.row.status === 'drafted'">执行</button> | ||||||
|  |                   <button class="operate-btn pause-btn" v-if="scope.row.status === 'in-progress'">暂停</button> | ||||||
|  |                   <button class="operate-btn resume-btn" v-if="scope.row.status === 'paused'">恢复</button> | ||||||
|  |                   <button class="operate-btn view-btn">查看详情</button> | ||||||
|  |                 </div> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |           </el-table> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <!-- 5.2 巡检任务表格 --> | ||||||
|  |         <div v-if="activeTab === 'task'" class="table-container"> | ||||||
|  |           <el-table :data="taskTableData" border> | ||||||
|  |             <el-table-column prop="name" label="任务名称" width="220"></el-table-column> | ||||||
|  |             <el-table-column prop="planName" label="所属计划" width="180"></el-table-column> | ||||||
|  |             <el-table-column prop="type" label="巡检类型" width="120"></el-table-column> | ||||||
|  |             <el-table-column prop="target" label="巡检对象" width="150"></el-table-column> | ||||||
|  |             <el-table-column prop="deadline" label="截止时间" width="160"></el-table-column> | ||||||
|  |             <el-table-column prop="status" label="状态" width="100"> | ||||||
|  |               <template #default="scope"> | ||||||
|  |                 <span :class="['status-tag', `status-${scope.row.status}`]"> | ||||||
|  |                   {{ getTaskStatusText(scope.row.status) }} | ||||||
|  |                 </span> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |             <el-table-column prop="executor" label="执行人" width="120"></el-table-column> | ||||||
|  |             <el-table-column label="操作" width="180"> | ||||||
|  |               <template #default="scope"> | ||||||
|  |                 <div class="operation-buttons"> | ||||||
|  |                   <button class="operate-btn accept-btn" v-if="scope.row.status === 'pending'">接受</button> | ||||||
|  |                   <button class="operate-btn complete-btn" v-if="scope.row.status === 'accepted'">完成</button> | ||||||
|  |                   <button class="operate-btn view-btn">查看详情</button> | ||||||
|  |                 </div> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |           </el-table> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 6. 分页 --> | ||||||
|  |       <div class="pagination" v-if="activeTab !== 'record'"> | ||||||
|  |         <p class="total-records">显示1到{{ pageSize }}条,共{{ totalRecords }}条记录</p> | ||||||
|  |         <el-pagination | ||||||
|  |           layout="prev, pager, next, jumper, sizes" | ||||||
|  |           :total="totalRecords" | ||||||
|  |           v-model:current-page="currentPage" | ||||||
|  |           v-model:page-size="pageSize" | ||||||
|  |           :page-sizes="[20, 50, 100]" | ||||||
|  |           @current-change="handlePageChange" | ||||||
|  |           @size-change="handleSizeChange" | ||||||
|  |         ></el-pagination> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <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); | ||||||
|  |  | ||||||
|  | // 2. 筛选条件 | ||||||
|  | const filterStatus = ref('all'); | ||||||
|  | const filterType = ref('all'); | ||||||
|  | const dateRange = ref([]); | ||||||
|  |  | ||||||
|  | // 4. 当前日期 | ||||||
|  | const currentDate = computed(() => { | ||||||
|  |   const date = new Date(); | ||||||
|  |   return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')} ${String( | ||||||
|  |     date.getHours() | ||||||
|  |   ).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 5. 统计数据 | ||||||
|  | const statData = ref({ | ||||||
|  |   completed: 12, | ||||||
|  |   passRate: 83, | ||||||
|  |   pendingAnalysis: 3, | ||||||
|  |   avgDuration: '42分钟' | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 6. 试验记录数据 | ||||||
|  | const testRecords = ref([ | ||||||
|  |   { | ||||||
|  |     date: '2025-06-15', | ||||||
|  |     duration: '1小时45分钟', | ||||||
|  |     responseTime: '1.2s', | ||||||
|  |     errorRate: '0%', | ||||||
|  |     temperature: '72°C' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     date: '2025-06-12', | ||||||
|  |     duration: '2小时10分钟' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 9. 方法:切换顶部导航 | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/shiyanrenwu'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/shiyanjilu'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | /* 1. 基础容器样式 */ | ||||||
|  | .operation-inspection { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f9fbfd; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 2. 顶部导航选项卡 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.2s; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #6b7280; | ||||||
|  |   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.active { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   color: #fff; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select, | ||||||
|  | .filter-bar .el-date-picker { | ||||||
|  |   width: 150px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  | /* 5. 筛选和操作区域 */ | ||||||
|  | .filter-and-actions { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   padding: 16px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border: 1px solid #e5e7eb; | ||||||
|  |   border-radius: 0 0 4px 4px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 12px; | ||||||
|  | } | ||||||
|  | .filters { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 12px; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  | } | ||||||
|  | .action-buttons { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 12px; | ||||||
|  | } | ||||||
|  | .el-select, | ||||||
|  | .date-picker { | ||||||
|  |   width: 160px; | ||||||
|  | } | ||||||
|  | .search-btn, | ||||||
|  | .export-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  | } | ||||||
|  | .filter-btn { | ||||||
|  |   background-color: #f3f4f6; | ||||||
|  |   color: #6b7280; | ||||||
|  |   border-color: #e5e7eb; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 6. 表格容器 */ | ||||||
|  | .table-container { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border: 1px solid #e5e7eb; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  | } | ||||||
|  | .el-table { | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  | .el-table th { | ||||||
|  |   background-color: #f9fafb; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #4b5563; | ||||||
|  | } | ||||||
|  | .plan-name { | ||||||
|  |   white-space: pre-line; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 7. 进度条样式 */ | ||||||
|  | .progress-bar { | ||||||
|  |   height: 8px; | ||||||
|  |   background-color: #f3f4f6; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  | .progress-fill { | ||||||
|  |   height: 100%; | ||||||
|  |   transition: width 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 8. 状态标签样式 */ | ||||||
|  | .status-tag { | ||||||
|  |   display: inline-block; | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  | .status-drafted { | ||||||
|  |   background-color: #e0efff; | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  | .status-in-progress { | ||||||
|  |   background-color: #e0f2fe; | ||||||
|  |   color: #0284c7; | ||||||
|  | } | ||||||
|  | .status-completed { | ||||||
|  |   background-color: #e6ffed; | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  | .status-paused { | ||||||
|  |   background-color: #f2f3f5; | ||||||
|  |   color: #86909c; | ||||||
|  | } | ||||||
|  | .status-pending { | ||||||
|  |   background-color: #f9fafb; | ||||||
|  |   color: #6b7280; | ||||||
|  | } | ||||||
|  | .status-accepted { | ||||||
|  |   background-color: #eff6ff; | ||||||
|  |   color: #2563eb; | ||||||
|  | } | ||||||
|  | .status-rejected { | ||||||
|  |   background-color: #fee2e2; | ||||||
|  |   color: #dc2626; | ||||||
|  | } | ||||||
|  | .status-normal { | ||||||
|  |   background-color: #e6ffed; | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  | .status-attention { | ||||||
|  |   background-color: #fff7e0; | ||||||
|  |   color: #ff7d00; | ||||||
|  | } | ||||||
|  | .status-problem { | ||||||
|  |   background-color: #fff2f0; | ||||||
|  |   color: #f5222d; | ||||||
|  | } | ||||||
|  | .status-passed { | ||||||
|  |   background-color: #e6ffed; | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  | .status-failed { | ||||||
|  |   background-color: #fee2e2; | ||||||
|  |   color: #dc2626; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 9. 操作按钮样式 */ | ||||||
|  | .operation-buttons { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 6px; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  | } | ||||||
|  | .operate-btn { | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   border: none; | ||||||
|  |   background: none; | ||||||
|  |   transition: all 0.2s; | ||||||
|  | } | ||||||
|  | .edit-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  | .edit-btn:hover { | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  | } | ||||||
|  | .execute-btn { | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  | .execute-btn:hover { | ||||||
|  |   background-color: #e6ffed; | ||||||
|  | } | ||||||
|  | .pause-btn { | ||||||
|  |   color: #ff7d00; | ||||||
|  | } | ||||||
|  | .pause-btn:hover { | ||||||
|  |   background-color: #fff7e0; | ||||||
|  | } | ||||||
|  | .resume-btn { | ||||||
|  |   color: #722ed1; | ||||||
|  | } | ||||||
|  | .resume-btn:hover { | ||||||
|  |   background-color: #f3e8ff; | ||||||
|  | } | ||||||
|  | .view-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  | .view-btn:hover { | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  | } | ||||||
|  | .complete-btn { | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  | .complete-btn:hover { | ||||||
|  |   background-color: #e6ffed; | ||||||
|  | } | ||||||
|  | .accept-btn { | ||||||
|  |   color: #2563eb; | ||||||
|  | } | ||||||
|  | .accept-btn:hover { | ||||||
|  |   background-color: #eff6ff; | ||||||
|  | } | ||||||
|  | .report-btn { | ||||||
|  |   color: #ff7d00; | ||||||
|  | } | ||||||
|  | .report-btn:hover { | ||||||
|  |   background-color: #fff7e0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 10. 分页样式 */ | ||||||
|  | .pagination { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   padding: 12px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border: 1px solid #e5e7eb; | ||||||
|  | } | ||||||
|  | .total-records { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #6b7280; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  | .el-pagination { | ||||||
|  |   --el-pagination-item-active-bg-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 11. 记录页面样式 */ | ||||||
|  | .record-container { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border: 1px solid #e5e7eb; | ||||||
|  |   padding: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .section-title { | ||||||
|  |   font-size: 18px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #1f2329; | ||||||
|  |   margin: 0 0 10px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .section-subtitle { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #6b7280; | ||||||
|  |   margin: 0 0 20px 0; | ||||||
|  |   text-align: right; | ||||||
|  | } | ||||||
|  | /* 头部容器 - 替换了固定gap的flex布局 */ | ||||||
|  | .header-container { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header-actions { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  | /* 12. 统计卡片样式 */ | ||||||
|  | .stat-grid { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(4, 1fr); | ||||||
|  |   gap: 16px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  | } | ||||||
|  | .stat-card { | ||||||
|  |   background-color: #f0f7ff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   padding: 16px; | ||||||
|  |   border-left: 4px solid #165dff; | ||||||
|  | } | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #6b7280; | ||||||
|  |   margin: 0 0 8px 0; | ||||||
|  | } | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #1f2329; | ||||||
|  |   margin: 0; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: baseline; | ||||||
|  |   gap: 8px; | ||||||
|  | } | ||||||
|  | .stat-change { | ||||||
|  |   font-size: 12px; | ||||||
|  |   padding: 1px 6px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   white-space: nowrap; | ||||||
|  | } | ||||||
|  | .stat-change.up { | ||||||
|  |   background-color: #e6ffed; | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  | .stat-change.down { | ||||||
|  |   background-color: #fff1f0; | ||||||
|  |   color: #f5222d; | ||||||
|  | } | ||||||
|  | .stat-change.warning { | ||||||
|  |   background-color: #fff7e0; | ||||||
|  |   color: #ff7d00; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 13. 试验记录样式 */ | ||||||
|  | .test-records { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   gap: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .test-record-card { | ||||||
|  |   border: 1px solid #e5e7eb; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   overflow: hidden; | ||||||
|  |   transition: box-shadow 0.2s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .test-record-card:hover { | ||||||
|  |   box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .test-record-card.passed { | ||||||
|  |   border-left: 4px solid #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .test-record-card.failed { | ||||||
|  |   border-left: 4px solid #dc2626; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-header { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   padding: 16px; | ||||||
|  |   background-color: #f9fafb; | ||||||
|  |   border-bottom: 1px solid #e5e7eb; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-title { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #1f2329; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-date { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #6b7280; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-time { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #9ca3af; | ||||||
|  |   margin-left: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 14. 试验进度样式 */ | ||||||
|  | .test-progress { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   gap: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-step { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   align-items: center; | ||||||
|  |   flex: 1; | ||||||
|  |   position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .step-number { | ||||||
|  |   width: 32px; | ||||||
|  |   height: 32px; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   background-color: #e5e7eb; | ||||||
|  |   color: #6b7280; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: center; | ||||||
|  |   font-weight: 600; | ||||||
|  |   margin-bottom: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .step-name { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #6b7280; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-line { | ||||||
|  |   flex: 1; | ||||||
|  |   height: 2px; | ||||||
|  |   background-color: #e5e7eb; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-step.active .step-number { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   color: white; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-step.active .step-name { | ||||||
|  |   color: #165dff; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-line.active { | ||||||
|  |   background-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-step.failed .step-number { | ||||||
|  |   background-color: #dc2626; | ||||||
|  |   color: white; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-step.failed .step-name { | ||||||
|  |   color: #dc2626; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-line.failed { | ||||||
|  |   background-color: #dc2626; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 15. 试验结果样式 */ | ||||||
|  | .test-result { | ||||||
|  |   padding: 16px 20px; | ||||||
|  |   border-top: 1px solid #e5e7eb; | ||||||
|  |   background-color: #fff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .result-title { | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #1f2329; | ||||||
|  |   margin: 0 0 12px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .result-content { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #4b5563; | ||||||
|  |   line-height: 1.5; | ||||||
|  |   margin: 0 0 12px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .result-details { | ||||||
|  |   font-size: 13px; | ||||||
|  |   color: #6b7280; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .failure-analysis { | ||||||
|  |   background-color: #fff5f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .improvement-suggestion { | ||||||
|  |   margin-top: 12px; | ||||||
|  |   padding: 10px 12px; | ||||||
|  |   background-color: #fff8e6; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   gap: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .improvement-suggestion i { | ||||||
|  |   color: #ff7d00; | ||||||
|  |   margin-top: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .improvement-suggestion p { | ||||||
|  |   font-size: 13px; | ||||||
|  |   color: #6b46c1; | ||||||
|  |   margin: 0; | ||||||
|  |   line-height: 1.5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 16. 记录操作按钮 */ | ||||||
|  | .record-actions { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: flex-end; | ||||||
|  |   gap: 10px; | ||||||
|  |   padding: 16px 20px; | ||||||
|  |   background-color: #f9fafb; | ||||||
|  |   border-top: 1px solid #e5e7eb; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 17. 响应式适配 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .stat-grid { | ||||||
|  |     grid-template-columns: repeat(2, 1fr); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .stat-grid { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .test-progress { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |     gap: 16px; | ||||||
|  |     padding: 16px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .progress-step { | ||||||
|  |     flex-direction: row; | ||||||
|  |     width: 100%; | ||||||
|  |     gap: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .step-number { | ||||||
|  |     margin-bottom: 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .progress-line { | ||||||
|  |     width: 2px; | ||||||
|  |     height: 30px; | ||||||
|  |     align-self: center; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filters { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .el-select, | ||||||
|  |   .date-picker { | ||||||
|  |     width: 100%; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .action-buttons { | ||||||
|  |     width: 100%; | ||||||
|  |     justify-content: space-between; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .navigation-tabs { | ||||||
|  |     flex-wrap: wrap; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .nav-tab { | ||||||
|  |     flex: 1 1 auto; | ||||||
|  |     min-width: 100px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .record-header { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |     gap: 8px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										800
									
								
								src/views/zhinengxunjian/shiyanrenwu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,800 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="inspection-tasks"> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 页面标题 --> | ||||||
|  |       <TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">巡检计划</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">巡检任务</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement3">巡检记录</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 筛选栏 --> | ||||||
|  |       <div class="filter-bar"> | ||||||
|  |         <div class="filter-container"> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="taskStatus" placeholder="任务状态"> | ||||||
|  |               <el-option label="待执行" value="pending"></el-option> | ||||||
|  |               <el-option label="执行中" value="executing"></el-option> | ||||||
|  |               <el-option label="已延期" value="delayed"></el-option> | ||||||
|  |               <el-option label="已完成" value="completed"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="planType" placeholder="全部计划"> | ||||||
|  |               <el-option label="每日巡检计划" value="daily"></el-option> | ||||||
|  |               <el-option label="每周巡检计划" value="weekly"></el-option> | ||||||
|  |               <el-option label="每月巡检计划" value="monthly"></el-option> | ||||||
|  |               <el-option label="每季度巡检计划" value="quarterly"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="executor" placeholder="执行人"> | ||||||
|  |               <el-option label="全部人员" value="all"></el-option> | ||||||
|  |               <el-option label="张明" value="zhangming"></el-option> | ||||||
|  |               <el-option label="李华" value="lihua"></el-option> | ||||||
|  |               <el-option label="王强" value="wangqiang"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-actions"> | ||||||
|  |             <el-button type="primary" class="search-btn">搜索</el-button> | ||||||
|  |             <el-button type="primary" icon="el-icon-plus" class="create-btn" @click="handleCreateTask"> 手动创建任务 </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 任务卡片列表 --> | ||||||
|  |       <div class="task-cards"> | ||||||
|  |         <div class="task-card" v-for="(task, index) in pagedTasks" :key="index" :class="task.cardClass"> | ||||||
|  |           <div class="task-header"> | ||||||
|  |             <div class="task-title"> | ||||||
|  |               {{ task.title }} | ||||||
|  |             </div> | ||||||
|  |             <div class="task-status" :class="task.tagClass"> | ||||||
|  |               <!-- 标签专用类名,控制标签样式 --> | ||||||
|  |               {{ task.statusText }} | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <div class="task-details"> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">计划时间</span> | ||||||
|  |               <span class="detail-value">{{ task.planTime }}</span> | ||||||
|  |             </div> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">巡检对象</span> | ||||||
|  |               <span class="detail-value">{{ task.target }}</span> | ||||||
|  |             </div> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">执行人</span> | ||||||
|  |               <span class="detail-value">{{ task.executor }}</span> | ||||||
|  |             </div> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">关联计划</span> | ||||||
|  |               <span class="detail-value">{{ task.relatedPlan }}</span> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <!-- 特定状态的额外信息 --> | ||||||
|  |             <div v-if="task.status === 'delayed'" class="delay-reason"> | ||||||
|  |               <span class="detail-label">延期原因</span> | ||||||
|  |               <span class="detail-value">{{ task.delayReason }}</span> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div v-if="task.status === 'executing'" class="progress-container"> | ||||||
|  |               <span class="detail-label">完成进度</span> | ||||||
|  |               <div class="progress-bar"> | ||||||
|  |                 <el-progress :percentage="task.progress" stroke-width="6" :stroke-color="task.progressColor"></el-progress> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div v-if="task.status === 'completed'" class="task-result"> | ||||||
|  |               <span class="detail-label">结果</span> | ||||||
|  |               <span class="detail-value" :class="task.resultClass">{{ task.result }}</span> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <div class="task-actions"> | ||||||
|  |             <el-button type="text" class="action-btn view-btn" @click="handleView(task)"> 详情 </el-button> | ||||||
|  |             <el-button type="primary" :class="task.actionClass" @click="handleAction(task)"> | ||||||
|  |               {{ task.actionText }} | ||||||
|  |             </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[8, 12, 16, 20]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 添加新任务弹窗 --> | ||||||
|  |       <el-dialog v-model="createTaskDialogVisible" title="添加新任务" width="500px" :before-close="handleCancelCreateTask"> | ||||||
|  |         <el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="80px"> | ||||||
|  |           <el-form-item label="任务名称" prop="taskName"> | ||||||
|  |             <el-input v-model="createTaskForm.taskName" placeholder="输入任务名称" /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="巡检对象" prop="inspectionTarget"> | ||||||
|  |             <el-input v-model="createTaskForm.inspectionTarget" placeholder="输入巡检内容" /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="时间" prop="timeRange"> | ||||||
|  |             <el-date-picker | ||||||
|  |               v-model="createTaskForm.timeRange" | ||||||
|  |               type="datetimerange" | ||||||
|  |               start-placeholder="开始时间" | ||||||
|  |               end-placeholder="结束时间" | ||||||
|  |               format="YYYY-MM-DD HH:mm" | ||||||
|  |               value-format="YYYY-MM-DD HH:mm" | ||||||
|  |               placeholder="选择时间范围" | ||||||
|  |             /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="关联计划"> | ||||||
|  |             <el-select v-model="createTaskForm.relatedPlan" placeholder="选择关联计划"> | ||||||
|  |               <el-option label="全部计划" value="all" /> | ||||||
|  |               <el-option label="每日巡检计划" value="daily" /> | ||||||
|  |               <el-option label="每周巡检计划" value="weekly" /> | ||||||
|  |               <el-option label="每月巡检计划" value="monthly" /> | ||||||
|  |               <el-option label="每季度巡检计划" value="quarterly" /> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="执行人"> | ||||||
|  |             <el-select v-model="createTaskForm.executor" placeholder="选择执行人"> | ||||||
|  |               <el-option label="全部人员" value="all" /> | ||||||
|  |               <el-option label="张明" value="zhangming" /> | ||||||
|  |               <el-option label="李华" value="lihua" /> | ||||||
|  |               <el-option label="王强" value="wangqiang" /> | ||||||
|  |               <el-option label="赵伟" value="zhaowei" /> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |         </el-form> | ||||||
|  |  | ||||||
|  |         <template #footer> | ||||||
|  |           <span class="dialog-footer"> | ||||||
|  |             <el-button @click="handleCancelCreateTask">取消</el-button> | ||||||
|  |             <el-button type="primary" @click="handleSaveTask">保存任务</el-button> | ||||||
|  |           </span> | ||||||
|  |         </template> | ||||||
|  |       </el-dialog> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 激活的选项卡 | ||||||
|  | const activeTab = ref('task'); | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const taskStatus = ref(''); | ||||||
|  | const planType = ref(''); | ||||||
|  | const executor = ref(''); | ||||||
|  |  | ||||||
|  | // 任务数据 - 分离了卡片类和标签类 | ||||||
|  | const tasks = ref([ | ||||||
|  |   { | ||||||
|  |     title: '生产服务器日常巡检', | ||||||
|  |     status: 'pending', | ||||||
|  |     statusText: '待执行', | ||||||
|  |     cardClass: 'card-pending', // 卡片专用类(控制阴影和左侧线) | ||||||
|  |     tagClass: 'tag-pending', // 标签专用类(控制标签样式) | ||||||
|  |     planTime: '2025-06-16 08:30', | ||||||
|  |     target: '生产服务器集群(12台)', | ||||||
|  |     executor: '张明', | ||||||
|  |     relatedPlan: '每日巡检计划', | ||||||
|  |     actionText: '开始执行', | ||||||
|  |     actionClass: 'start-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '机房环境检查', | ||||||
|  |     status: 'delayed', | ||||||
|  |     statusText: '已延期', | ||||||
|  |     cardClass: 'card-delayed', | ||||||
|  |     tagClass: 'tag-delayed', | ||||||
|  |     planTime: '2025-06-16 08:30', | ||||||
|  |     target: '机房温度、湿度、电源', | ||||||
|  |     executor: '李华', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     delayReason: '设备维修处理中', | ||||||
|  |     actionText: '重新安排', | ||||||
|  |     actionClass: 'reschedule-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '网络设备安全巡检', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '执行中', | ||||||
|  |     cardClass: 'card-executing', | ||||||
|  |     tagClass: 'tag-executing', | ||||||
|  |     planTime: '2025-06-16 09:30', | ||||||
|  |     target: '核心交换机、防火墙', | ||||||
|  |     executor: '王强', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     progress: 60, | ||||||
|  |     progressColor: '#FF7D00', | ||||||
|  |     actionText: '完成', | ||||||
|  |     actionClass: 'complete-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '数据库性能巡检', | ||||||
|  |     status: 'completed', | ||||||
|  |     statusText: '已完成', | ||||||
|  |     cardClass: 'card-completed', | ||||||
|  |     tagClass: 'tag-completed', | ||||||
|  |     planTime: '2025-06-16 10:30', | ||||||
|  |     target: '生产数据库集群(2组)', | ||||||
|  |     executor: '赵伟', | ||||||
|  |     relatedPlan: '每月巡检计划', | ||||||
|  |     result: '正常', | ||||||
|  |     resultClass: 'result-normal', | ||||||
|  |     actionText: '查看报告', | ||||||
|  |     actionClass: 'report-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '生产服务器日常巡检', | ||||||
|  |     status: 'pending', | ||||||
|  |     statusText: '待执行', | ||||||
|  |     cardClass: 'card-pending', | ||||||
|  |     tagClass: 'tag-pending', | ||||||
|  |     planTime: '2025-06-16 13:30', | ||||||
|  |     target: '生产服务器集群(12台)', | ||||||
|  |     executor: '张明', | ||||||
|  |     relatedPlan: '每日巡检计划', | ||||||
|  |     actionText: '开始执行', | ||||||
|  |     actionClass: 'start-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '机房环境检查', | ||||||
|  |     status: 'delayed', | ||||||
|  |     statusText: '已延期', | ||||||
|  |     cardClass: 'card-delayed', | ||||||
|  |     tagClass: 'tag-delayed', | ||||||
|  |     planTime: '2025-06-16 14:00', | ||||||
|  |     target: '机房温度、湿度、电源', | ||||||
|  |     executor: '李华', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     delayReason: '设备维修处理中', | ||||||
|  |     actionText: '重新安排', | ||||||
|  |     actionClass: 'reschedule-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '网络设备安全巡检', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '执行中', | ||||||
|  |     cardClass: 'card-executing', | ||||||
|  |     tagClass: 'tag-executing', | ||||||
|  |     planTime: '2025-06-16 15:00', | ||||||
|  |     target: '核心交换机、防火墙', | ||||||
|  |     executor: '王强', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     progress: 35, | ||||||
|  |     progressColor: '#FF7D00', | ||||||
|  |     actionText: '完成', | ||||||
|  |     actionClass: 'complete-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '数据库性能巡检', | ||||||
|  |     status: 'completed', | ||||||
|  |     statusText: '已完成', | ||||||
|  |     cardClass: 'card-completed', | ||||||
|  |     tagClass: 'tag-completed', | ||||||
|  |     planTime: '2025-06-16 16:00', | ||||||
|  |     target: '生产数据库集群(2组)', | ||||||
|  |     executor: '赵伟', | ||||||
|  |     relatedPlan: '每月巡检计划', | ||||||
|  |     result: '正常', | ||||||
|  |     resultClass: 'result-normal', | ||||||
|  |     actionText: '查看报告', | ||||||
|  |     actionClass: 'report-btn' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 分页相关 | ||||||
|  | const currentPage = ref(1); | ||||||
|  | const pageSize = ref(8); | ||||||
|  | const total = ref(tasks.value.length); | ||||||
|  |  | ||||||
|  | // 状态排序映射 | ||||||
|  | const statusOrder = { | ||||||
|  |   pending: 0, // 待完成 | ||||||
|  |   delayed: 1, // 已延期 | ||||||
|  |   executing: 2, // 执行中 | ||||||
|  |   completed: 3 // 已完成 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页处理后的数据(含排序) | ||||||
|  | const pagedTasks = computed(() => { | ||||||
|  |   // 先按状态排序 | ||||||
|  |   const sortedTasks = [...tasks.value].sort((a, b) => { | ||||||
|  |     return statusOrder[a.status] - statusOrder[b.status]; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   // 再进行分页 | ||||||
|  |   const startIndex = (currentPage.value - 1) * pageSize.value; | ||||||
|  |   const endIndex = startIndex + pageSize.value; | ||||||
|  |   return sortedTasks.slice(startIndex, endIndex); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 搜索处理 | ||||||
|  | const handleSearch = () => { | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  |   // 实际应用中这里会根据筛选条件过滤数据 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建任务弹窗相关 | ||||||
|  | const createTaskDialogVisible = ref(false); | ||||||
|  | const createTaskForm = ref({ | ||||||
|  |   taskName: '', | ||||||
|  |   inspectionTarget: '', | ||||||
|  |   timeRange: [], | ||||||
|  |   relatedPlan: 'all', | ||||||
|  |   executor: 'all' | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | const createTaskRules = { | ||||||
|  |   taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }], | ||||||
|  |   inspectionTarget: [{ required: true, message: '请输入巡检对象', trigger: 'blur' }], | ||||||
|  |   timeRange: [{ required: true, message: '请选择时间范围', trigger: 'change' }] | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建任务 | ||||||
|  | const handleCreateTask = () => { | ||||||
|  |   createTaskDialogVisible.value = true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 保存任务 | ||||||
|  | const handleSaveTask = () => { | ||||||
|  |   // 模拟保存任务逻辑 | ||||||
|  |   console.log('保存任务:', createTaskForm.value); | ||||||
|  |   // 关闭弹窗 | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     taskName: '', | ||||||
|  |     inspectionTarget: '', | ||||||
|  |     timeRange: [], | ||||||
|  |     relatedPlan: 'all', | ||||||
|  |     executor: 'all' | ||||||
|  |   }; | ||||||
|  |   // 这里可以添加成功提示和刷新任务列表的逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 取消创建任务 | ||||||
|  | const handleCancelCreateTask = () => { | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     taskName: '', | ||||||
|  |     inspectionTarget: '', | ||||||
|  |     timeRange: [], | ||||||
|  |     relatedPlan: 'all', | ||||||
|  |     executor: 'all' | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页事件 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 查看任务详情 | ||||||
|  | const handleView = (task) => { | ||||||
|  |   console.log('查看任务详情:', task); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/xunjianrenwu'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/xunjianjihua'); | ||||||
|  | }; | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .inspection-tasks { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-container { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select { | ||||||
|  |   width: 180px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-btn { | ||||||
|  |   background-color: #f2f3f5; | ||||||
|  |   color: #303133; | ||||||
|  |   border-color: #f2f3f5; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .create-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 任务卡片样式 */ | ||||||
|  | .task-cards { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); | ||||||
|  |   gap: 20px; | ||||||
|  |   margin-bottom: 30px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card { | ||||||
|  |   background-color: #fff; /* 确保卡片背景始终为白色 */ | ||||||
|  |   border-radius: 8px; | ||||||
|  |   padding: 16px 16px 60px 24px; /* 左侧留空间给状态线 */ | ||||||
|  |   position: relative; | ||||||
|  |   overflow: hidden; | ||||||
|  |   min-height: 280px; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 卡片左侧状态竖线 - 仅用于左侧标识 */ | ||||||
|  | .task-card::before { | ||||||
|  |   content: ''; | ||||||
|  |   position: absolute; | ||||||
|  |   left: 0; | ||||||
|  |   top: 0; | ||||||
|  |   bottom: 0; | ||||||
|  |   width: 6px; | ||||||
|  |   box-shadow: 0 0 8px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 卡片阴影样式 - 与状态关联但不影响背景色 */ | ||||||
|  | .card-pending { | ||||||
|  |   box-shadow: 0 4px 16px rgba(22, 119, 255, 0.15); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .card-delayed { | ||||||
|  |   box-shadow: 0 4px 16px rgba(255, 77, 79, 0.15); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .card-executing { | ||||||
|  |   box-shadow: 0 4px 16px rgba(250, 140, 22, 0.15); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .card-completed { | ||||||
|  |   box-shadow: 0 4px 16px rgba(82, 196, 26, 0.15); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 左侧状态线颜色 */ | ||||||
|  | .card-pending::before { | ||||||
|  |   background-color: #1677ff; | ||||||
|  | } | ||||||
|  | .card-delayed::before { | ||||||
|  |   background-color: #ff4d4f; | ||||||
|  | } | ||||||
|  | .card-executing::before { | ||||||
|  |   background-color: #fa8c16; | ||||||
|  | } | ||||||
|  | .card-completed::before { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 卡片悬停效果 */ | ||||||
|  | .task-card:hover { | ||||||
|  |   transform: translateY(-3px); | ||||||
|  |   box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1), 0 4px 16px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-header { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   padding-bottom: 12px; | ||||||
|  |   border-bottom: 1px solid #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-title { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #1d2129; | ||||||
|  |   line-height: 1.4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 状态标签样式 - 仅标签有背景色 */ | ||||||
|  | .task-status { | ||||||
|  |   padding: 4px 10px; | ||||||
|  |   border-radius: 6px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   border: 1px solid transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tag-pending { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  |   color: #1677ff; | ||||||
|  |   border-color: #91d5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tag-delayed { | ||||||
|  |   background-color: #fff2f0; | ||||||
|  |   color: #ff4d4f; | ||||||
|  |   border-color: #ffccc7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tag-executing { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #fa8c16; | ||||||
|  |   border-color: #ffe58f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tag-completed { | ||||||
|  |   background-color: #f6ffed; | ||||||
|  |   color: #52c41a; | ||||||
|  |   border-color: #b7eb8f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-details { | ||||||
|  |   margin-bottom: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-item { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 10px; | ||||||
|  |   font-size: 13px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-label { | ||||||
|  |   flex: 0 0 80px; | ||||||
|  |   color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-value { | ||||||
|  |   flex: 1; | ||||||
|  |   color: #4e5969; | ||||||
|  |   word-break: break-all; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .delay-reason { | ||||||
|  |   display: flex; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding-top: 8px; | ||||||
|  |   border-top: 1px dashed #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-container { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   padding-top: 8px; | ||||||
|  |   border-top: 1px dashed #f0f2f5; | ||||||
|  |   z-index: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-bar { | ||||||
|  |   flex: 1; | ||||||
|  |   padding-left: 80px; | ||||||
|  |   margin-top: 4px; | ||||||
|  |   position: relative; | ||||||
|  |   z-index: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-result { | ||||||
|  |   display: flex; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding-top: 8px; | ||||||
|  |   border-top: 1px dashed #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .result-normal { | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .result-abnormal { | ||||||
|  |   color: #f53f3f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-actions { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: flex-end; | ||||||
|  |   align-items: center; | ||||||
|  |   padding-top: 12px; | ||||||
|  |   border-top: 1px solid #f0f2f5; | ||||||
|  |   position: absolute; | ||||||
|  |   bottom: 16px; | ||||||
|  |   right: 16px; | ||||||
|  |   left: 16px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 12px 0 0 0; | ||||||
|  |   z-index: 10; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn { | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding: 4px 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .view-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .start-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .reschedule-btn { | ||||||
|  |   background-color: #ff7d00; | ||||||
|  |   border-color: #ff7d00; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .complete-btn { | ||||||
|  |   background-color: #00b42a; | ||||||
|  |   border-color: #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .report-btn { | ||||||
|  |   background-color: #86909c; | ||||||
|  |   border-color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .pagination-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   margin-top: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .task-cards { | ||||||
|  |     grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .inspection-tasks { | ||||||
|  |     padding: 16px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .task-cards { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										923
									
								
								src/views/zhinengxunjian/xunjianjihua.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,923 @@ | |||||||
|  | <template> | ||||||
|  |   <div class="operation-inspection"> | ||||||
|  |     <div class="navigation-tabs"> | ||||||
|  |       <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |       <div class="nav-tab active" @click="handleInspection2">巡检管理</div> | ||||||
|  |       <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |       <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |       <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |       <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |       <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> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- 选项卡和按钮组合 --> | ||||||
|  |     <div class="tabs-wrapper"> | ||||||
|  |       <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |         <el-button type="primary" @click="handleInspectionManagement1">巡检计划</el-button> | ||||||
|  |         <el-button type="primary" @click="handleInspectionManagement2">巡检任务</el-button> | ||||||
|  |         <el-button type="primary" @click="handleInspectionManagement3">巡检记录</el-button> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- 筛选栏 --> | ||||||
|  |     <div class="filter-bar"> | ||||||
|  |       <div class="filter-item"> | ||||||
|  |         <el-select v-model="filterStatus" placeholder="状态" clearable> | ||||||
|  |           <el-option label="全部状态" value="all"></el-option> | ||||||
|  |           <el-option label="正常" value="normal"></el-option> | ||||||
|  |           <el-option label="需关注" value="attention"></el-option> | ||||||
|  |           <el-option label="有问题" value="problem"></el-option> | ||||||
|  |         </el-select> | ||||||
|  |       </div> | ||||||
|  |       <div class="filter-item"> | ||||||
|  |         <el-select v-model="filterType" placeholder="巡检类型" clearable> | ||||||
|  |           <el-option label="全部类型" value="all"></el-option> | ||||||
|  |           <el-option label="数据库" value="database"></el-option> | ||||||
|  |           <el-option label="服务器" value="server"></el-option> | ||||||
|  |           <el-option label="网络设备" value="network"></el-option> | ||||||
|  |         </el-select> | ||||||
|  |       </div> | ||||||
|  |       <div class="filter-item"> | ||||||
|  |         <el-date-picker | ||||||
|  |           v-model="dateRange" | ||||||
|  |           type="daterange" | ||||||
|  |           range-separator="至" | ||||||
|  |           start-placeholder="开始日期" | ||||||
|  |           end-placeholder="结束日期" | ||||||
|  |           value-format="YYYY-MM-DD" | ||||||
|  |         ></el-date-picker> | ||||||
|  |       </div> | ||||||
|  |       <div class="filter-actions"> | ||||||
|  |         <el-button type="primary" class="search-btn" @click="fetchDashboardData">搜索</el-button> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- 主内容区 - 使用flex确保等高 --> | ||||||
|  |     <div class="main-content-container"> | ||||||
|  |       <!-- 左侧和中间内容区 --> | ||||||
|  |       <div class="left-content"> | ||||||
|  |         <!-- 巡检记录与报告卡片 --> | ||||||
|  |         <div class="content-card"> | ||||||
|  |           <div class="card-header"> | ||||||
|  |             <h2 class="card-title">巡检记录与报告</h2> | ||||||
|  |             <div class="flex space-x-2"> | ||||||
|  |               <button | ||||||
|  |                 class="px-3 py-1 text-sm rounded-md hover:bg-gray-200 transition" | ||||||
|  |                 :class="{ 'bg-gray-100 text-gray-700': timeRange === 'month', 'bg-white text-gray-500': timeRange !== 'month' }" | ||||||
|  |                 @click="handleTimeRangeChange('month')" | ||||||
|  |               > | ||||||
|  |                 月 | ||||||
|  |               </button> | ||||||
|  |               <button | ||||||
|  |                 class="px-3 py-1 text-sm rounded-md hover:bg-gray-100 transition" | ||||||
|  |                 :class="{ 'bg-gray-100 text-gray-700': timeRange === 'week', 'bg-white text-gray-500': timeRange !== 'week' }" | ||||||
|  |                 @click="handleTimeRangeChange('week')" | ||||||
|  |               > | ||||||
|  |                 周 | ||||||
|  |               </button> | ||||||
|  |               <button | ||||||
|  |                 class="px-3 py-1 text-sm rounded-md hover:bg-gray-100 transition" | ||||||
|  |                 :class="{ 'bg-gray-100 text-gray-700': timeRange === 'day', 'bg-white text-gray-500': timeRange !== 'day' }" | ||||||
|  |                 @click="handleTimeRangeChange('day')" | ||||||
|  |               > | ||||||
|  |                 日 | ||||||
|  |               </button> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 数据卡片 --> | ||||||
|  |           <div class="card-body"> | ||||||
|  |             <div class="grid grid-cols-2 md:grid-cols-4 gap-4"> | ||||||
|  |               <div class="stat-card"> | ||||||
|  |                 <p class="stat-label">本月完成巡检</p> | ||||||
|  |                 <p class="stat-value">{{ completedInspections }}</p> | ||||||
|  |               </div> | ||||||
|  |               <div class="stat-card"> | ||||||
|  |                 <p class="stat-label">发现问题数</p> | ||||||
|  |                 <p class="stat-value">{{ totalProblems }}</p> | ||||||
|  |               </div> | ||||||
|  |               <div class="stat-card"> | ||||||
|  |                 <p class="stat-label">已解决问题</p> | ||||||
|  |                 <p class="stat-value">{{ solvedProblems }}</p> | ||||||
|  |               </div> | ||||||
|  |               <div class="stat-card"> | ||||||
|  |                 <p class="stat-label">平均完成时间</p> | ||||||
|  |                 <p class="stat-value">{{ avgCompletionTime }}</p> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div class="divider"></div> | ||||||
|  |  | ||||||
|  |             <!-- 图表区域 --> | ||||||
|  |             <div class="grid grid-cols-1 md:grid-cols-3 gap-6 py-4"> | ||||||
|  |               <!-- 饼图 - 使用指定的ECharts配置 --> | ||||||
|  |               <div class="md:col-span-1"> | ||||||
|  |                 <p class="chart-title">进度指标对比</p> | ||||||
|  |                 <div ref="pieChartRef" class="pie-chart-container"></div> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 进度条 --> | ||||||
|  |               <div class="md:col-span-2 flex flex-col justify-center"> | ||||||
|  |                 <div class="space-y-4"> | ||||||
|  |                   <div> | ||||||
|  |                     <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                       <span class="text-gray-600">完成率</span> | ||||||
|  |                       <span class="font-medium text-gray-800">{{ completionRate }}%</span> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                       <div class="bg-blue-500 h-2 rounded-full transition-all duration-1500 ease-out" :style="{ width: completionRate + '%' }"></div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                   <div> | ||||||
|  |                     <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                       <span class="text-gray-600">解决率</span> | ||||||
|  |                       <span class="font-medium text-gray-800">{{ resolutionRate }}%</span> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                       <div class="bg-red-500 h-2 rounded-full transition-all duration-1500 ease-out" :style="{ width: resolutionRate + '%' }"></div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                   <div> | ||||||
|  |                     <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                       <span class="text-gray-600">及时率</span> | ||||||
|  |                       <span class="font-medium text-gray-800">{{ timelinessRate }}%</span> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                       <div class="bg-green-500 h-2 rounded-full transition-all duration-1500 ease-out" :style="{ width: timelinessRate + '%' }"></div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div class="divider"></div> | ||||||
|  |  | ||||||
|  |             <!-- 发现问题种类 --> | ||||||
|  |             <div class="py-4"> | ||||||
|  |               <h3 class="section-title">发现问题种类</h3> | ||||||
|  |               <div class="space-y-4"> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">温度异常率</span> | ||||||
|  |                     <span class="text-gray-500">{{ problemTypes.temperature }}%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                     <div | ||||||
|  |                       class="bg-blue-500 h-2 rounded-full transition-all duration-1500 ease-out" | ||||||
|  |                       :style="{ width: problemTypes.temperature + '%' }" | ||||||
|  |                     ></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">内存使用率</span> | ||||||
|  |                     <span class="text-gray-500">{{ problemTypes.memory }}%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                     <div | ||||||
|  |                       class="bg-blue-500 h-2 rounded-full transition-all duration-1500 ease-out" | ||||||
|  |                       :style="{ width: problemTypes.memory + '%' }" | ||||||
|  |                     ></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">CPU负载</span> | ||||||
|  |                     <span class="text-gray-500">{{ problemTypes.cpu }}%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                     <div class="bg-blue-500 h-2 rounded-full transition-all duration-1500 ease-out" :style="{ width: problemTypes.cpu + '%' }"></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">响应时间</span> | ||||||
|  |                     <span class="text-gray-500">{{ problemTypes.responseTime }}%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                     <div | ||||||
|  |                       class="bg-blue-500 h-2 rounded-full transition-all duration-1500 ease-out" | ||||||
|  |                       :style="{ width: problemTypes.responseTime + '%' }" | ||||||
|  |                     ></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">磁盘空间状态</span> | ||||||
|  |                     <span class="text-gray-500">{{ problemTypes.diskSpace }}%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2 overflow-hidden"> | ||||||
|  |                     <div | ||||||
|  |                       class="bg-blue-500 h-2 rounded-full transition-all duration-1500 ease-out" | ||||||
|  |                       :style="{ width: problemTypes.diskSpace + '%' }" | ||||||
|  |                     ></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 右侧最近巡检结果 --> | ||||||
|  |       <div class="right-content"> | ||||||
|  |         <div class="content-card h-full flex flex-col"> | ||||||
|  |           <div class="card-header"> | ||||||
|  |             <h2 class="card-title">最近巡检结果</h2> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 巡检结果列表 - 添加滚动样式 --> | ||||||
|  |           <div class="card-body flex-1 overflow-y-auto scrollbar-thin"> | ||||||
|  |             <div class="inspection-results space-y-4"> | ||||||
|  |               <!-- 结果1:正常 --> | ||||||
|  |               <div class="inspection-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm hover:shadow-md transition-shadow"> | ||||||
|  |                 <div class="flex justify-between items-start mb-4"> | ||||||
|  |                   <h3 class="text-lg font-medium text-gray-800">数据库性能巡检</h3> | ||||||
|  |                   <span class="status-tag status-normal px-3 py-1 text-xs">正常</span> | ||||||
|  |                 </div> | ||||||
|  |                 <p class="text-sm text-gray-500 mb-3">2025-06-15 14:00-16:45 张明</p> | ||||||
|  |  | ||||||
|  |                 <div class="flex justify-between items-center mb-4"> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">系统连接量</span> | ||||||
|  |                     <span class="text-sm font-medium">128</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">查询响应时间</span> | ||||||
|  |                     <span class="text-sm font-medium">平均0.3S</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">表空间使用率</span> | ||||||
|  |                     <span class="text-sm font-medium">75%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">日志文件</span> | ||||||
|  |                     <span class="text-sm font-medium">正常轮转</span> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="flex justify-end gap-2"> | ||||||
|  |                   <el-button size="small" class="text-sm border-gray-300 text-gray-600">查看详情</el-button> | ||||||
|  |                   <el-button type="primary" size="small" class="text-sm">生成报告</el-button> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 结果2:需关注 --> | ||||||
|  |               <div class="inspection-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm hover:shadow-md transition-shadow"> | ||||||
|  |                 <div class="flex justify-between items-start mb-4"> | ||||||
|  |                   <h3 class="text-lg font-medium text-gray-800">生产服务器日常巡检</h3> | ||||||
|  |                   <span class="status-tag status-attention px-3 py-1 text-xs">需关注</span> | ||||||
|  |                 </div> | ||||||
|  |                 <p class="text-sm text-gray-500 mb-3">2025-06-15 14:00-16:45 张明</p> | ||||||
|  |  | ||||||
|  |                 <div class="flex justify-between items-center mb-4"> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">CPU使用率</span> | ||||||
|  |                     <span class="text-sm font-medium">平均35%,峰值59%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-exclamation-circle text-yellow-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">内存使用率</span> | ||||||
|  |                     <span class="text-sm font-medium">85%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">磁盘空间</span> | ||||||
|  |                     <span class="text-sm font-medium">62%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">服务状态</span> | ||||||
|  |                     <span class="text-sm font-medium">正常运行</span> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="bg-yellow-50 border border-yellow-200 rounded-md p-3 mb-4"> | ||||||
|  |                   <div class="flex items-start"> | ||||||
|  |                     <i class="fas fa-info-circle text-yellow-500 mt-0.5 mr-2"></i> | ||||||
|  |                     <p class="text-xs text-yellow-800">已创建问题单 #PRB-2023061501,计划于今晚进行内存扩容</p> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="flex justify-end gap-2"> | ||||||
|  |                   <el-button size="small" class="text-sm border-gray-300 text-gray-600">查看详情</el-button> | ||||||
|  |                   <el-button type="primary" size="small" class="text-sm">生成报告</el-button> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |  | ||||||
|  |               <!-- 结果3:有问题 --> | ||||||
|  |               <div class="inspection-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm hover:shadow-md transition-shadow"> | ||||||
|  |                 <div class="flex justify-between items-start mb-4"> | ||||||
|  |                   <h3 class="text-lg font-medium text-gray-800">网络设备安全巡检</h3> | ||||||
|  |                   <span class="status-tag status-problem px-3 py-1 text-xs">有问题</span> | ||||||
|  |                 </div> | ||||||
|  |                 <p class="text-sm text-gray-500 mb-3">2025-06-14 10:00-11:30 李华</p> | ||||||
|  |  | ||||||
|  |                 <div class="grid grid-cols-2 gap-2 mb-4"> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-times-circle text-red-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">防火墙规则</span> | ||||||
|  |                     <span class="text-sm font-medium">部分规则异常</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-exclamation-circle text-yellow-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">安全补丁</span> | ||||||
|  |                     <span class="text-sm font-medium">需更新</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">访问控制</span> | ||||||
|  |                     <span class="text-sm font-medium">正常</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex flex-col items-center"> | ||||||
|  |                     <i class="fas fa-check-circle text-green-500 text-lg mb-1"></i> | ||||||
|  |                     <span class="text-xs text-gray-600 mb-1">流量监控</span> | ||||||
|  |                     <span class="text-sm font-medium">正常</span> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="flex justify-end gap-2"> | ||||||
|  |                   <el-button size="small" class="text-sm border-gray-300 text-gray-600">查看详情</el-button> | ||||||
|  |                   <el-button type="primary" size="small" class="text-sm">生成报告</el-button> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, onMounted, computed, onUnmounted } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const filterStatus = ref('all'); | ||||||
|  | const filterType = ref('all'); | ||||||
|  | const dateRange = ref([]); | ||||||
|  |  | ||||||
|  | // 时间范围选择 | ||||||
|  | const timeRange = ref('month'); // 默认选中"月" | ||||||
|  |  | ||||||
|  | // 进度指标数据 | ||||||
|  | const completionRate = ref(68); // 完成率 | ||||||
|  | const resolutionRate = ref(72); // 解决率 | ||||||
|  | const timelinessRate = ref(60); // 及时率 | ||||||
|  |  | ||||||
|  | // 统计数据 | ||||||
|  | const completedInspections = ref(42); | ||||||
|  | const totalProblems = ref(7); | ||||||
|  | const solvedProblems = ref(5); | ||||||
|  | const avgCompletionTime = ref('45分钟'); | ||||||
|  |  | ||||||
|  | // 问题类型数据 | ||||||
|  | const problemTypes = ref({ | ||||||
|  |   temperature: 85, // 温度异常率 | ||||||
|  |   memory: 62, // 内存使用率 | ||||||
|  |   cpu: 45, // CPU负载 | ||||||
|  |   responseTime: 30, // 响应时间 | ||||||
|  |   diskSpace: 15 // 磁盘空间状态 | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // ECharts 饼图相关 | ||||||
|  | const pieChartRef = ref(null); | ||||||
|  | let pieChart = null; | ||||||
|  |  | ||||||
|  | // 计算平均完成度 | ||||||
|  | const averageRate = computed(() => (completionRate.value + resolutionRate.value + timelinessRate.value) / 3); | ||||||
|  |  | ||||||
|  | // 初始化饼图 - 使用指定的option配置 | ||||||
|  | const initPieChart = () => { | ||||||
|  |   // 确保DOM元素已存在 | ||||||
|  |   if (!pieChartRef.value) return; | ||||||
|  |  | ||||||
|  |   // 销毁已存在的实例 | ||||||
|  |   if (pieChart) { | ||||||
|  |     pieChart.dispose(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // 创建新实例 | ||||||
|  |   pieChart = echarts.init(pieChartRef.value); | ||||||
|  |  | ||||||
|  |   // 设置图表配置 - 使用指定的option | ||||||
|  |   const option = { | ||||||
|  |     tooltip: { | ||||||
|  |       trigger: 'item' | ||||||
|  |     }, | ||||||
|  |     legend: { | ||||||
|  |       top: '5%', | ||||||
|  |       left: 'center' | ||||||
|  |     }, | ||||||
|  |     series: [ | ||||||
|  |       { | ||||||
|  |         name: '进度指标', | ||||||
|  |         type: 'pie', | ||||||
|  |         radius: ['40%', '70%'], | ||||||
|  |         avoidLabelOverlap: false, | ||||||
|  |         padAngle: 5, | ||||||
|  |         itemStyle: { | ||||||
|  |           borderRadius: 10 | ||||||
|  |         }, | ||||||
|  |         label: { | ||||||
|  |           show: false, | ||||||
|  |           position: 'center' | ||||||
|  |         }, | ||||||
|  |         emphasis: { | ||||||
|  |           label: { | ||||||
|  |             show: true, | ||||||
|  |             fontSize: 40, | ||||||
|  |             fontWeight: 'bold', | ||||||
|  |             formatter: function (params) { | ||||||
|  |               // 鼠标悬停时显示当前指标的百分比 | ||||||
|  |               return params.value + '%'; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         labelLine: { | ||||||
|  |           show: false | ||||||
|  |         }, | ||||||
|  |         data: [ | ||||||
|  |           { value: completionRate.value, name: '完成率', itemStyle: { color: '#5470c6' } }, | ||||||
|  |           { value: resolutionRate.value, name: '解决率', itemStyle: { color: '#f56c6c' } }, | ||||||
|  |           { value: timelinessRate.value, name: '及时率', itemStyle: { color: '#67c23a' } } | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // 设置配置项 | ||||||
|  |   pieChart.setOption(option); | ||||||
|  |  | ||||||
|  |   // 响应窗口大小变化 | ||||||
|  |   const handleResize = () => { | ||||||
|  |     if (pieChart) { | ||||||
|  |       pieChart.resize(); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   window.addEventListener('resize', handleResize); | ||||||
|  |  | ||||||
|  |   // 组件卸载时移除事件监听 | ||||||
|  |   onUnmounted(() => { | ||||||
|  |     window.removeEventListener('resize', handleResize); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 时间范围切换函数 | ||||||
|  | const handleTimeRangeChange = (range) => { | ||||||
|  |   timeRange.value = range; | ||||||
|  |   fetchDashboardData(); // 切换时间范围时重新获取数据 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 获取仪表盘数据(模拟) | ||||||
|  | const fetchDashboardData = () => { | ||||||
|  |   // 模拟加载状态 | ||||||
|  |   completionRate.value = 0; | ||||||
|  |   resolutionRate.value = 0; | ||||||
|  |   timelinessRate.value = 0; | ||||||
|  |  | ||||||
|  |   // 模拟API请求延迟 | ||||||
|  |   setTimeout(() => { | ||||||
|  |     // 根据时间范围返回不同数据 | ||||||
|  |     let mockData; | ||||||
|  |     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 | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |     } 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 | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |     } 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 | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 应用筛选条件(这里仅做简单演示) | ||||||
|  |     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); // 模拟网络延迟 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 页面加载时获取数据 | ||||||
|  | onMounted(() => { | ||||||
|  |   fetchDashboardData(); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 组件卸载时销毁图表实例 | ||||||
|  | onUnmounted(() => { | ||||||
|  |   if (pieChart) { | ||||||
|  |     pieChart.dispose(); | ||||||
|  |     pieChart = null; | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 导航方法 | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/xunjianrenwu'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/xunjianjihua'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | /* 主容器样式 */ | ||||||
|  | .operation-inspection { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 头部容器 */ | ||||||
|  | .header-container { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header-actions { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   cursor: pointer; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select, | ||||||
|  | .filter-bar .el-date-picker { | ||||||
|  |   width: 150px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-btn, | ||||||
|  | .export-btn, | ||||||
|  | .create-btn { | ||||||
|  |   height: 36px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 主内容区 - 使用flex确保等高 */ | ||||||
|  | .main-content-container { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 20px; | ||||||
|  |   height: calc(100% - 20px); | ||||||
|  |   min-height: 500px; /* 确保有最小高度 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .left-content { | ||||||
|  |   flex: 2; /* 左侧占2/3宽度 */ | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .right-content { | ||||||
|  |   flex: 1; /* 右侧占1/3宽度 */ | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 内容卡片样式 */ | ||||||
|  | .content-card { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  |   overflow: hidden; | ||||||
|  |   height: 100%; /* 卡片高度占满容器 */ | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .card-header { | ||||||
|  |   padding: 20px; | ||||||
|  |   border-bottom: 1px solid #e4e7ed; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .card-title { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .card-body { | ||||||
|  |   padding: 20px; | ||||||
|  |   flex: 1; /* 内容区域占满剩余空间 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计卡片样式 */ | ||||||
|  | .stat-card { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   border-radius: 6px; | ||||||
|  |   padding: 16px; | ||||||
|  |   transition: transform 0.3s ease, box-shadow 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-card:hover { | ||||||
|  |   transform: translateY(-3px); | ||||||
|  |   box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   margin: 0 0 8px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .stat-value { | ||||||
|  |   font-size: 24px; | ||||||
|  |   font-weight: 600; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分隔线 */ | ||||||
|  | .divider { | ||||||
|  |   height: 1px; | ||||||
|  |   background-color: #e4e7ed; | ||||||
|  |   margin: 16px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 图表标题 */ | ||||||
|  | .chart-title { | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   margin: 0 0 8px 0; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 饼图容器 */ | ||||||
|  | .pie-chart-container { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 300px; | ||||||
|  |   margin: 0 auto; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 区域标题 */ | ||||||
|  | .section-title { | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0 0 12px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 状态标签 */ | ||||||
|  | .status-tag { | ||||||
|  |   font-size: 12px; | ||||||
|  |   padding: 2px 8px; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-normal { | ||||||
|  |   background-color: #f0f9eb; | ||||||
|  |   color: #52c41a; | ||||||
|  |   border: 1px solid #e1f3d8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-attention { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #faad14; | ||||||
|  |   border: 1px solid #fff1b8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-problem { | ||||||
|  |   background-color: #fff2f0; | ||||||
|  |   color: #f5222d; | ||||||
|  |   border: 1px solid #ffe3e0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 滚动条样式优化 */ | ||||||
|  | .scrollbar-thin { | ||||||
|  |   scrollbar-width: thin; | ||||||
|  |   scrollbar-color: #d1d5db #f3f4f6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollbar-thin::-webkit-scrollbar { | ||||||
|  |   width: 6px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollbar-thin::-webkit-scrollbar-track { | ||||||
|  |   background: #f3f4f6; | ||||||
|  |   border-radius: 3px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollbar-thin::-webkit-scrollbar-thumb { | ||||||
|  |   background-color: #d1d5db; | ||||||
|  |   border-radius: 3px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .scrollbar-thin::-webkit-scrollbar-thumb:hover { | ||||||
|  |   background-color: #9ca3af; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .main-content-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-bar { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-actions { | ||||||
|  |     margin-left: 0; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .grid-cols-2 { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .md\:col-span-1, | ||||||
|  |   .md\:col-span-2, | ||||||
|  |   .md\:col-span-3 { | ||||||
|  |     grid-column: span 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .md\:grid-cols-4, | ||||||
|  |   .md\:grid-cols-3 { | ||||||
|  |     grid-template-columns: 1fr 1fr; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .navigation-tabs { | ||||||
|  |     justify-content: flex-start; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										789
									
								
								src/views/zhinengxunjian/xunjianrenwu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,789 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <div class="inspection-tasks"> | ||||||
|  |       <div class="navigation-tabs"> | ||||||
|  |         <div class="nav-tab" @click="handleInspection1">待办事项</div> | ||||||
|  |         <div class="nav-tab active" @click="handleInspection2">巡检管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection3">试验管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection4">报修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection5">抢修管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection6">工单管理</div> | ||||||
|  |         <div class="nav-tab" @click="handleInspection7">运维组织</div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 页面标题 --> | ||||||
|  |       <TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent> | ||||||
|  |  | ||||||
|  |       <!-- 选项卡 --> | ||||||
|  |       <div class="tabs-wrapper"> | ||||||
|  |         <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement1">巡检计划</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement2">巡检任务</el-button> | ||||||
|  |           <el-button type="primary" @click="handleInspectionManagement3">巡检记录</el-button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 筛选栏 --> | ||||||
|  |       <div class="filter-bar"> | ||||||
|  |         <div class="filter-container"> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="taskStatus" placeholder="任务状态"> | ||||||
|  |               <el-option label="待执行" value="pending"></el-option> | ||||||
|  |               <el-option label="执行中" value="executing"></el-option> | ||||||
|  |               <el-option label="已延期" value="delayed"></el-option> | ||||||
|  |               <el-option label="已完成" value="completed"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="planType" placeholder="全部计划"> | ||||||
|  |               <el-option label="每日巡检计划" value="daily"></el-option> | ||||||
|  |               <el-option label="每周巡检计划" value="weekly"></el-option> | ||||||
|  |               <el-option label="每月巡检计划" value="monthly"></el-option> | ||||||
|  |               <el-option label="每季度巡检计划" value="quarterly"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-item"> | ||||||
|  |             <el-select v-model="executor" placeholder="执行人"> | ||||||
|  |               <el-option label="全部人员" value="all"></el-option> | ||||||
|  |               <el-option label="张明" value="zhangming"></el-option> | ||||||
|  |               <el-option label="李华" value="lihua"></el-option> | ||||||
|  |               <el-option label="王强" value="wangqiang"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |           </div> | ||||||
|  |           <div class="filter-actions"> | ||||||
|  |             <el-button type="primary" class="search-btn">搜索</el-button> | ||||||
|  |             <el-button type="primary" icon="el-icon-plus" class="create-btn" @click="handleCreateTask"> 手动创建任务 </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 任务卡片列表 --> | ||||||
|  |       <div class="task-cards"> | ||||||
|  |         <div class="task-card" v-for="(task, index) in pagedTasks" :key="index" :class="task.statusClass"> | ||||||
|  |           <div class="task-header"> | ||||||
|  |             <div class="task-title"> | ||||||
|  |               {{ task.title }} | ||||||
|  |             </div> | ||||||
|  |             <div class="task-status" :class="task.tagClass"> | ||||||
|  |               {{ task.statusText }} | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <div class="task-details"> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">计划时间</span> | ||||||
|  |               <span class="detail-value">{{ task.planTime }}</span> | ||||||
|  |             </div> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">巡检对象</span> | ||||||
|  |               <span class="detail-value">{{ task.target }}</span> | ||||||
|  |             </div> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">执行人</span> | ||||||
|  |               <span class="detail-value">{{ task.executor }}</span> | ||||||
|  |             </div> | ||||||
|  |             <div class="detail-item"> | ||||||
|  |               <span class="detail-label">关联计划</span> | ||||||
|  |               <span class="detail-value">{{ task.relatedPlan }}</span> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <!-- 特定状态的额外信息 --> | ||||||
|  |             <div v-if="task.status === 'delayed'" class="delay-reason"> | ||||||
|  |               <span class="detail-label">延期原因</span> | ||||||
|  |               <span class="detail-value">{{ task.delayReason }}</span> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div v-if="task.status === 'executing'" class="progress-container"> | ||||||
|  |               <span class="detail-label">完成进度</span> | ||||||
|  |               <div class="progress-bar"> | ||||||
|  |                 <el-progress :percentage="task.progress" stroke-width="6" :stroke-color="task.progressColor"></el-progress> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div v-if="task.status === 'completed'" class="task-result"> | ||||||
|  |               <span class="detail-label">结果</span> | ||||||
|  |               <span class="detail-value" :class="task.resultClass">{{ task.result }}</span> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <div class="task-actions"> | ||||||
|  |             <el-button type="text" class="action-btn view-btn" @click="handleView(task)"> 详情 </el-button> | ||||||
|  |             <el-button type="primary" :class="task.actionClass" @click="handleAction(task)"> | ||||||
|  |               {{ task.actionText }} | ||||||
|  |             </el-button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 分页区域 --> | ||||||
|  |       <div class="pagination-section"> | ||||||
|  |         <div class="pagination-controls"> | ||||||
|  |           <el-pagination | ||||||
|  |             @size-change="handleSizeChange" | ||||||
|  |             @current-change="handleCurrentChange" | ||||||
|  |             :current-page="currentPage" | ||||||
|  |             :page-sizes="[8, 12, 16, 20]" | ||||||
|  |             :page-size="pageSize" | ||||||
|  |             layout="prev, pager, next, jumper" | ||||||
|  |             :total="total" | ||||||
|  |             background | ||||||
|  |           > | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 添加新任务弹窗 --> | ||||||
|  |       <el-dialog v-model="createTaskDialogVisible" title="添加新任务" width="500px" :before-close="handleCancelCreateTask"> | ||||||
|  |         <el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="80px"> | ||||||
|  |           <el-form-item label="任务名称" prop="taskName"> | ||||||
|  |             <el-input v-model="createTaskForm.taskName" placeholder="输入任务名称" /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="巡检对象" prop="inspectionTarget"> | ||||||
|  |             <el-input v-model="createTaskForm.inspectionTarget" placeholder="输入巡检内容" /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="时间" prop="timeRange"> | ||||||
|  |             <el-date-picker | ||||||
|  |               v-model="createTaskForm.timeRange" | ||||||
|  |               type="datetimerange" | ||||||
|  |               start-placeholder="开始时间" | ||||||
|  |               end-placeholder="结束时间" | ||||||
|  |               format="YYYY-MM-DD HH:mm" | ||||||
|  |               value-format="YYYY-MM-DD HH:mm" | ||||||
|  |               placeholder="选择时间范围" | ||||||
|  |             /> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="关联计划"> | ||||||
|  |             <el-select v-model="createTaskForm.relatedPlan" placeholder="选择关联计划"> | ||||||
|  |               <el-option label="全部计划" value="all" /> | ||||||
|  |               <el-option label="每日巡检计划" value="daily" /> | ||||||
|  |               <el-option label="每周巡检计划" value="weekly" /> | ||||||
|  |               <el-option label="每月巡检计划" value="monthly" /> | ||||||
|  |               <el-option label="每季度巡检计划" value="quarterly" /> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |  | ||||||
|  |           <el-form-item label="执行人"> | ||||||
|  |             <el-select v-model="createTaskForm.executor" placeholder="选择执行人"> | ||||||
|  |               <el-option label="全部人员" value="all" /> | ||||||
|  |               <el-option label="张明" value="zhangming" /> | ||||||
|  |               <el-option label="李华" value="lihua" /> | ||||||
|  |               <el-option label="王强" value="wangqiang" /> | ||||||
|  |               <el-option label="赵伟" value="zhaowei" /> | ||||||
|  |             </el-select> | ||||||
|  |           </el-form-item> | ||||||
|  |         </el-form> | ||||||
|  |  | ||||||
|  |         <template #footer> | ||||||
|  |           <span class="dialog-footer"> | ||||||
|  |             <el-button @click="handleCancelCreateTask">取消</el-button> | ||||||
|  |             <el-button type="primary" @click="handleSaveTask">保存任务</el-button> | ||||||
|  |           </span> | ||||||
|  |         </template> | ||||||
|  |       </el-dialog> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from './TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 激活的选项卡 | ||||||
|  | const activeTab = ref('task'); | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const taskStatus = ref(''); | ||||||
|  | const planType = ref(''); | ||||||
|  | const executor = ref(''); | ||||||
|  |  | ||||||
|  | // 任务数据 - 分离卡片状态类和标签状态类 | ||||||
|  | const tasks = ref([ | ||||||
|  |   { | ||||||
|  |     title: '生产服务器日常巡检', | ||||||
|  |     status: 'pending', | ||||||
|  |     statusText: '待执行', | ||||||
|  |     statusClass: 'card-pending', // 仅用于卡片左侧线和阴影 | ||||||
|  |     tagClass: 'tag-pending', // 仅用于标签样式 | ||||||
|  |     planTime: '2025-06-16 08:30', | ||||||
|  |     target: '生产服务器集群(12台)', | ||||||
|  |     executor: '张明', | ||||||
|  |     relatedPlan: '每日巡检计划', | ||||||
|  |     actionText: '开始执行', | ||||||
|  |     actionClass: 'start-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '机房环境检查', | ||||||
|  |     status: 'delayed', | ||||||
|  |     statusText: '已延期', | ||||||
|  |     statusClass: 'card-delayed', | ||||||
|  |     tagClass: 'tag-delayed', | ||||||
|  |     planTime: '2025-06-16 08:30', | ||||||
|  |     target: '机房温度、湿度、电源', | ||||||
|  |     executor: '李华', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     delayReason: '设备维修处理中', | ||||||
|  |     actionText: '重新安排', | ||||||
|  |     actionClass: 'reschedule-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '网络设备安全巡检', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '执行中', | ||||||
|  |     statusClass: 'card-executing', | ||||||
|  |     tagClass: 'tag-executing', | ||||||
|  |     planTime: '2025-06-16 09:30', | ||||||
|  |     target: '核心交换机、防火墙', | ||||||
|  |     executor: '王强', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     progress: 60, | ||||||
|  |     progressColor: '#FF7D00', | ||||||
|  |     actionText: '完成', | ||||||
|  |     actionClass: 'complete-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '数据库性能巡检', | ||||||
|  |     status: 'completed', | ||||||
|  |     statusText: '已完成', | ||||||
|  |     statusClass: 'card-completed', | ||||||
|  |     tagClass: 'tag-completed', | ||||||
|  |     planTime: '2025-06-16 10:30', | ||||||
|  |     target: '生产数据库集群(2组)', | ||||||
|  |     executor: '赵伟', | ||||||
|  |     relatedPlan: '每月巡检计划', | ||||||
|  |     result: '正常', | ||||||
|  |     resultClass: 'result-normal', | ||||||
|  |     actionText: '查看报告', | ||||||
|  |     actionClass: 'report-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '生产服务器日常巡检', | ||||||
|  |     status: 'pending', | ||||||
|  |     statusText: '待执行', | ||||||
|  |     statusClass: 'card-pending', | ||||||
|  |     tagClass: 'tag-pending', | ||||||
|  |     planTime: '2025-06-16 13:30', | ||||||
|  |     target: '生产服务器集群(12台)', | ||||||
|  |     executor: '张明', | ||||||
|  |     relatedPlan: '每日巡检计划', | ||||||
|  |     actionText: '开始执行', | ||||||
|  |     actionClass: 'start-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '机房环境检查', | ||||||
|  |     status: 'delayed', | ||||||
|  |     statusText: '已延期', | ||||||
|  |     statusClass: 'card-delayed', | ||||||
|  |     tagClass: 'tag-delayed', | ||||||
|  |     planTime: '2025-06-16 14:00', | ||||||
|  |     target: '机房温度、湿度、电源', | ||||||
|  |     executor: '李华', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     delayReason: '设备维修处理中', | ||||||
|  |     actionText: '重新安排', | ||||||
|  |     actionClass: 'reschedule-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '网络设备安全巡检', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '执行中', | ||||||
|  |     statusClass: 'card-executing', | ||||||
|  |     tagClass: 'tag-executing', | ||||||
|  |     planTime: '2025-06-16 15:00', | ||||||
|  |     target: '核心交换机、防火墙', | ||||||
|  |     executor: '王强', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     progress: 35, | ||||||
|  |     progressColor: '#FF7D00', | ||||||
|  |     actionText: '完成', | ||||||
|  |     actionClass: 'complete-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '数据库性能巡检', | ||||||
|  |     status: 'completed', | ||||||
|  |     statusText: '已完成', | ||||||
|  |     statusClass: 'card-completed', | ||||||
|  |     tagClass: 'tag-completed', | ||||||
|  |     planTime: '2025-06-16 16:00', | ||||||
|  |     target: '生产数据库集群(2组)', | ||||||
|  |     executor: '赵伟', | ||||||
|  |     relatedPlan: '每月巡检计划', | ||||||
|  |     result: '正常', | ||||||
|  |     resultClass: 'result-normal', | ||||||
|  |     actionText: '查看报告', | ||||||
|  |     actionClass: 'report-btn' | ||||||
|  |   } | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | // 分页相关 | ||||||
|  | const currentPage = ref(1); | ||||||
|  | const pageSize = ref(8); | ||||||
|  | const total = ref(tasks.value.length); | ||||||
|  |  | ||||||
|  | // 状态排序映射 | ||||||
|  | const statusOrder = { | ||||||
|  |   pending: 0, // 待完成 | ||||||
|  |   delayed: 1, // 已延期 | ||||||
|  |   executing: 2, // 执行中 | ||||||
|  |   completed: 3 // 已完成 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页处理后的数据(含排序) | ||||||
|  | const pagedTasks = computed(() => { | ||||||
|  |   // 先按状态排序 | ||||||
|  |   const sortedTasks = [...tasks.value].sort((a, b) => { | ||||||
|  |     return statusOrder[a.status] - statusOrder[b.status]; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   // 再进行分页 | ||||||
|  |   const startIndex = (currentPage.value - 1) * pageSize.value; | ||||||
|  |   const endIndex = startIndex + pageSize.value; | ||||||
|  |   return sortedTasks.slice(startIndex, endIndex); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 搜索处理 | ||||||
|  | const handleSearch = () => { | ||||||
|  |   currentPage.value = 1; // 重置到第一页 | ||||||
|  |   // 实际应用中这里会根据筛选条件过滤数据 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建任务弹窗相关 | ||||||
|  | const createTaskDialogVisible = ref(false); | ||||||
|  | const createTaskForm = ref({ | ||||||
|  |   taskName: '', | ||||||
|  |   inspectionTarget: '', | ||||||
|  |   timeRange: [], | ||||||
|  |   relatedPlan: 'all', | ||||||
|  |   executor: 'all' | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | const createTaskRules = { | ||||||
|  |   taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }], | ||||||
|  |   inspectionTarget: [{ required: true, message: '请输入巡检对象', trigger: 'blur' }], | ||||||
|  |   timeRange: [{ required: true, message: '请选择时间范围', trigger: 'change' }] | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 创建任务 | ||||||
|  | const handleCreateTask = () => { | ||||||
|  |   createTaskDialogVisible.value = true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 保存任务 | ||||||
|  | const handleSaveTask = () => { | ||||||
|  |   // 模拟保存任务逻辑 | ||||||
|  |   console.log('保存任务:', createTaskForm.value); | ||||||
|  |   // 关闭弹窗 | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     taskName: '', | ||||||
|  |     inspectionTarget: '', | ||||||
|  |     timeRange: [], | ||||||
|  |     relatedPlan: 'all', | ||||||
|  |     executor: 'all' | ||||||
|  |   }; | ||||||
|  |   // 这里可以添加成功提示和刷新任务列表的逻辑 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 取消创建任务 | ||||||
|  | const handleCancelCreateTask = () => { | ||||||
|  |   createTaskDialogVisible.value = false; | ||||||
|  |   // 重置表单 | ||||||
|  |   createTaskForm.value = { | ||||||
|  |     taskName: '', | ||||||
|  |     inspectionTarget: '', | ||||||
|  |     timeRange: [], | ||||||
|  |     relatedPlan: 'all', | ||||||
|  |     executor: 'all' | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 分页事件 | ||||||
|  | const handleSizeChange = (val) => { | ||||||
|  |   pageSize.value = val; | ||||||
|  |   currentPage.value = 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleCurrentChange = (val) => { | ||||||
|  |   currentPage.value = val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 查看任务详情 | ||||||
|  | const handleView = (task) => { | ||||||
|  |   console.log('查看任务详情:', task); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement1 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const handleInspectionManagement2 = () => { | ||||||
|  |   router.push('/rili/xunjianrenwu'); | ||||||
|  | }; | ||||||
|  | const handleInspectionManagement3 = () => { | ||||||
|  |   router.push('/rili/xunjianjihua'); | ||||||
|  | }; | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | const handleInspection3 = () => { | ||||||
|  |   router.push('/rili/shiyanguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection4 = () => { | ||||||
|  |   router.push('/rili/baoxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection5 = () => { | ||||||
|  |   router.push('/rili/qiangxiuguanli'); | ||||||
|  | }; | ||||||
|  | const handleInspection6 = () => { | ||||||
|  |   router.push('/rili/gongdanliebiao'); | ||||||
|  | }; | ||||||
|  | const handleInspection7 = () => { | ||||||
|  |   router.push('/rili/renyuanzhuangtai'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .inspection-tasks { | ||||||
|  |   padding: 20px; | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   min-height: 100vh; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 选项卡样式 */ | ||||||
|  | .tabs-wrapper { | ||||||
|  |   background-color: #fff; | ||||||
|  |   padding: 20px; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 筛选栏样式 */ | ||||||
|  | .filter-bar { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   margin-bottom: 24px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-container { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   gap: 16px; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-item { | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select { | ||||||
|  |   width: 180px; | ||||||
|  |   height: 36px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-actions { | ||||||
|  |   margin-left: auto; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .search-btn { | ||||||
|  |   background-color: #f2f3f5; | ||||||
|  |   color: #303133; | ||||||
|  |   border-color: #f2f3f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .create-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 任务卡片样式 */ | ||||||
|  | .task-cards { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); | ||||||
|  |   gap: 20px; | ||||||
|  |   margin-bottom: 30px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card { | ||||||
|  |   background-color: #fff; /* 强制卡片背景为白色 */ | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); | ||||||
|  |   padding: 16px 16px 60px 24px; /* 左侧留空间给状态线 */ | ||||||
|  |   position: relative; | ||||||
|  |   overflow: hidden; | ||||||
|  |   min-height: 280px; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 卡片左侧状态竖线 */ | ||||||
|  | .task-card::before { | ||||||
|  |   content: ''; | ||||||
|  |   position: absolute; | ||||||
|  |   left: 0; | ||||||
|  |   top: 0; | ||||||
|  |   bottom: 0; | ||||||
|  |   width: 6px; /* 加宽状态线 */ | ||||||
|  |   box-shadow: 0 0 8px rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 卡片状态类 - 仅控制左侧线和阴影 */ | ||||||
|  | .card-pending::before { | ||||||
|  |   background-color: #1677ff; | ||||||
|  | } | ||||||
|  | .card-delayed::before { | ||||||
|  |   background-color: #ff4d4f; | ||||||
|  | } | ||||||
|  | .card-executing::before { | ||||||
|  |   background-color: #fa8c16; | ||||||
|  | } | ||||||
|  | .card-completed::before { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 卡片阴影效果 */ | ||||||
|  | .card-pending { | ||||||
|  |   box-shadow: 0 4px 16px rgba(22, 119, 255, 0.15); | ||||||
|  | } | ||||||
|  | .card-delayed { | ||||||
|  |   box-shadow: 0 4px 16px rgba(255, 77, 79, 0.15); | ||||||
|  | } | ||||||
|  | .card-executing { | ||||||
|  |   box-shadow: 0 4px 16px rgba(250, 140, 22, 0.15); | ||||||
|  | } | ||||||
|  | .card-completed { | ||||||
|  |   box-shadow: 0 4px 16px rgba(82, 196, 26, 0.15); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card:hover { | ||||||
|  |   transform: translateY(-3px); | ||||||
|  |   box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-header { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   margin-bottom: 16px; | ||||||
|  |   padding-bottom: 12px; | ||||||
|  |   border-bottom: 1px solid #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-title { | ||||||
|  |   font-size: 16px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #1d2129; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 状态标签样式 - 仅作用于标签本身 */ | ||||||
|  | .task-status { | ||||||
|  |   padding: 4px 10px; | ||||||
|  |   border-radius: 6px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 标签状态类 - 仅控制标签样式 */ | ||||||
|  | .tag-pending { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  |   color: #1677ff; | ||||||
|  |   border: 1px solid #91d5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tag-delayed { | ||||||
|  |   background-color: #fff2f0; | ||||||
|  |   color: #ff4d4f; | ||||||
|  |   border: 1px solid #ffccc7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tag-executing { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #fa8c16; | ||||||
|  |   border: 1px solid #ffe58f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tag-completed { | ||||||
|  |   background-color: #f6ffed; | ||||||
|  |   color: #52c41a; | ||||||
|  |   border: 1px solid #b7eb8f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-details { | ||||||
|  |   margin-bottom: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-item { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 10px; | ||||||
|  |   font-size: 13px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-label { | ||||||
|  |   flex: 0 0 80px; | ||||||
|  |   color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .detail-value { | ||||||
|  |   flex: 1; | ||||||
|  |   color: #4e5969; | ||||||
|  |   word-break: break-all; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .delay-reason { | ||||||
|  |   display: flex; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding-top: 8px; | ||||||
|  |   border-top: 1px dashed #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-container { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   padding-top: 8px; | ||||||
|  |   border-top: 1px dashed #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-bar { | ||||||
|  |   flex: 1; | ||||||
|  |   padding-left: 80px; | ||||||
|  |   margin-top: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-result { | ||||||
|  |   display: flex; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding-top: 8px; | ||||||
|  |   border-top: 1px dashed #f0f2f5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .result-normal { | ||||||
|  |   color: #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .result-abnormal { | ||||||
|  |   color: #f53f3f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-actions { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: flex-end; | ||||||
|  |   align-items: center; | ||||||
|  |   padding-top: 12px; | ||||||
|  |   border-top: 1px solid #f0f2f5; | ||||||
|  |   position: absolute; | ||||||
|  |   bottom: 16px; | ||||||
|  |   right: 16px; | ||||||
|  |   left: 16px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   z-index: 10; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn { | ||||||
|  |   font-size: 13px; | ||||||
|  |   padding: 4px 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .view-btn { | ||||||
|  |   color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .start-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .reschedule-btn { | ||||||
|  |   background-color: #ff7d00; | ||||||
|  |   border-color: #ff7d00; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .complete-btn { | ||||||
|  |   background-color: #00b42a; | ||||||
|  |   border-color: #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .report-btn { | ||||||
|  |   background-color: #86909c; | ||||||
|  |   border-color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .pagination-section { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   margin-top: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .navigation-tabs { | ||||||
|  |   display: flex; | ||||||
|  |   margin-bottom: 20px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); | ||||||
|  |   padding: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab { | ||||||
|  |   padding: 12px 24px; | ||||||
|  |   cursor: pointer; | ||||||
|  |   transition: all 0.3s ease; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #606266; | ||||||
|  |   border-right: 1px solid #f0f0f0; | ||||||
|  |   flex: 1; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:last-child { | ||||||
|  |   border-right: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab:hover { | ||||||
|  |   color: #409eff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tab.active { | ||||||
|  |   background-color: #409eff; | ||||||
|  |   color: #fff; | ||||||
|  |   box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .task-cards { | ||||||
|  |     grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 768px) { | ||||||
|  |   .inspection-tasks { | ||||||
|  |     padding: 16px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-container { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .task-cards { | ||||||
|  |     grid-template-columns: 1fr; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||