合并
This commit is contained in:
		| @ -34,7 +34,7 @@ | |||||||
|     "date-fns": "^4.1.0", |     "date-fns": "^4.1.0", | ||||||
|     "diagram-js": "12.3.0", |     "diagram-js": "12.3.0", | ||||||
|     "didi": "9.0.2", |     "didi": "9.0.2", | ||||||
|     "echarts": "5.5.0", |     "echarts": "^5.5.0", | ||||||
|     "echarts-gl": "^2.0.9", |     "echarts-gl": "^2.0.9", | ||||||
|     "element-plus": "2.8.8", |     "element-plus": "2.8.8", | ||||||
|     "esbuild": "^0.25.0", |     "esbuild": "^0.25.0", | ||||||
|  | |||||||
| @ -106,6 +106,6 @@ export const getFootNote = (data) => { | |||||||
|   return request({ |   return request({ | ||||||
|     url: 'gps/equipmentSon/getList', |     url: 'gps/equipmentSon/getList', | ||||||
|     method: 'get', |     method: 'get', | ||||||
|     data: data |     params: data | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -122,6 +122,11 @@ export interface EquipmentQuery extends PageQuery { | |||||||
|    */ |    */ | ||||||
|   type?: string | number; |   type?: string | number; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 展示用户/设备数据:1=用户数据,0=设备数据 | ||||||
|  |    */ | ||||||
|  |   gpsType?: string | number; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * 用户id |    * 用户id | ||||||
|    */ |    */ | ||||||
|  | |||||||
| @ -1,17 +1,18 @@ | |||||||
| <template> | <template> | ||||||
|   <el-row> |   <el-row> | ||||||
|     <el-col> |     <el-col> | ||||||
|             <div style="color: rgba(0, 30, 59, 1);;font-family: 'Alibaba-PuHuiTi-Bold';margin: 10px 0 0 0;" |       <div | ||||||
|                 :style="{ fontSize: fontLevelMap[props.fontLevel] }"> |         style="color: rgba(0, 30, 59, 1); font-family: 'Alibaba-PuHuiTi-Bold'; margin: 10px 0 0 0" | ||||||
|  |         :style="{ fontSize: fontLevelMap[props.fontLevel] }" | ||||||
|  |       > | ||||||
|         {{ props.title }} |         {{ props.title }} | ||||||
|       </div> |       </div> | ||||||
|     </el-col> |     </el-col> | ||||||
|     <el-col> |     <el-col> | ||||||
|             <p style="color: rgba(154, 154, 154, 1);font-size: 14px;"> |       <p style="color: rgba(154, 154, 154, 1); font-size: 14px"> | ||||||
|         {{ props.subtitle }} |         {{ props.subtitle }} | ||||||
|       </p> |       </p> | ||||||
|     </el-col> |     </el-col> | ||||||
|  |  | ||||||
|   </el-row> |   </el-row> | ||||||
| </template> | </template> | ||||||
| <script setup> | <script setup> | ||||||
| @ -22,9 +23,9 @@ const props = defineProps({ | |||||||
|     type: Number, |     type: Number, | ||||||
|     default: 1 |     default: 1 | ||||||
|   } |   } | ||||||
| }) | }); | ||||||
| const fontLevelMap = { | const fontLevelMap = { | ||||||
|     1: "24px", |   1: '24px', | ||||||
|     2: "18px" |   2: '18px' | ||||||
| } | }; | ||||||
| </script> | </script> | ||||||
							
								
								
									
										756
									
								
								src/views/dhr_demo/InspectionManagement.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										756
									
								
								src/views/dhr_demo/InspectionManagement.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,756 @@ | |||||||
|  | <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">试验管理</div> | ||||||
|  |         <div class="nav-tab">报修管理</div> | ||||||
|  |         <div class="nav-tab">抢修管理</div> | ||||||
|  |         <div class="nav-tab">工单管理</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)" size="small" class="action-btn">编辑</el-button> | ||||||
|  |               <el-button type="text" @click="handleDetail(scope.row)" size="small" class="action-btn">详情</el-button> | ||||||
|  |               <el-button | ||||||
|  |                 type="text" | ||||||
|  |                 :disabled="scope.row.status === 'disabled'" | ||||||
|  |                 @click="handleEnable(scope.row)" | ||||||
|  |                 size="small" | ||||||
|  |                 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 '@/views/demo/components/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 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> | ||||||
							
								
								
									
										700
									
								
								src/views/dhr_demo/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										700
									
								
								src/views/dhr_demo/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,700 @@ | |||||||
|  | <template> | ||||||
|  |   <div class="container"> | ||||||
|  |     <!-- 导航栏 --> | ||||||
|  |     <div class="navigation-tabs"> | ||||||
|  |       <div class="nav-tab active" @click="handleInspection1">待办事项</div> | ||||||
|  |       <div class="nav-tab" @click="handleInspection2">巡检管理</div> | ||||||
|  |       <div class="nav-tab">试验管理</div> | ||||||
|  |       <div class="nav-tab">报修管理</div> | ||||||
|  |       <div class="nav-tab">抢修管理</div> | ||||||
|  |       <div class="nav-tab">工单管理</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-select v-model="selectedYear" placeholder="选择年份" size="small" style="width: 80px; margin-right: 5px"> | ||||||
|  |               <el-option v-for="year in years" :key="year" :label="year.toString()" :value="year"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |             <el-select v-model="selectedMonth" placeholder="选择月份" size="small" style="width: 80px; margin-right: 10px"> | ||||||
|  |               <el-option v-for="month in 12" :key="month" :label="month.toString()" :value="month"></el-option> | ||||||
|  |             </el-select> | ||||||
|  |             <!-- 月份切换按钮 --> | ||||||
|  |             <el-button type="text" icon="el-icon-arrow-left" @click="decreaseMonth"></el-button> | ||||||
|  |             <el-button type="text" icon="el-icon-arrow-right" @click="increaseMonth"></el-button> | ||||||
|  |             <el-button type="primary" size="small">添加</el-button> | ||||||
|  |             <el-button type="primary" size="small" @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> | ||||||
|  |  | ||||||
|  |           <!-- 待办项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"> | ||||||
|  |               <el-button type="text" icon="el-icon-edit"></el-button> | ||||||
|  |               <el-button type="text" icon="el-icon-delete"></el-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> | ||||||
|  |  | ||||||
|  |           <!-- 待办项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> | ||||||
|  |  | ||||||
|  |           <!-- 待办项5 - 常规维护 --> | ||||||
|  |           <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> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <!-- 状态图例 - 标签形式 --> | ||||||
|  |         <div class="status-legend"> | ||||||
|  |           <span class="status-tag normal">常规维护</span> | ||||||
|  |           <span class="status-tag important">重要</span> | ||||||
|  |           <span class="status-tag urgent">紧急</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> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import { ref, computed, watch } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from '../demo/components/TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 生成年份选项,生成2020-2029年的年份范围 | ||||||
|  | const targetYear = 2025; | ||||||
|  | const years = ref(Array.from({ length: 10 }, (_, index) => 2020 + index)); | ||||||
|  | const selectedYear = ref(targetYear); | ||||||
|  | const selectedMonth = ref(9); | ||||||
|  |  | ||||||
|  | // 默认显示2025年9月 | ||||||
|  | const currentDate = ref(new Date(targetYear, 8, 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([selectedYear, selectedMonth], ([newYear, newMonth]) => { | ||||||
|  |   const date = new Date(currentDate.value); | ||||||
|  |   date.setFullYear(newYear); | ||||||
|  |   date.setMonth(newMonth - 1); | ||||||
|  |   currentDate.value = date; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 初始化年份和月份选择器 | ||||||
|  | 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 handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .container { | ||||||
|  |   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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 日历区域样式 */ | ||||||
|  | .calendar-container { | ||||||
|  |   flex: 1; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   padding: 20px; | ||||||
|  |   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 自定义弹窗样式 */ | ||||||
|  | .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 { | ||||||
|  |   width: 400px; | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   padding: 20px; | ||||||
|  |   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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: 400px; | ||||||
|  |   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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 重要任务的背景色 */ | ||||||
|  | .todo-item.important { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-checkbox { | ||||||
|  |   margin-top: 2px; | ||||||
|  |   flex-shrink: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-content { | ||||||
|  |   flex: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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: 10px; | ||||||
|  |   bottom: 10px; | ||||||
|  |   display: flex; | ||||||
|  |   gap: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .todo-actions .el-button { | ||||||
|  |   padding: 4px 8px; | ||||||
|  |   min-width: auto; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 状态图例 - 标签形式 */ | ||||||
|  | .status-legend { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 10px; | ||||||
|  |   padding-top: 15px; | ||||||
|  |   border-top: 1px solid #ebeef5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag { | ||||||
|  |   display: inline-block; | ||||||
|  |   padding: 4px 12px; | ||||||
|  |   border-radius: 16px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #fff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.normal { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.important { | ||||||
|  |   background-color: #faad14; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .status-tag.urgent { | ||||||
|  |   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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 自定义日历单元格样式 */ | ||||||
|  | .custom-date-cell { | ||||||
|  |   padding: 5px; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 系统升级事件样式 */ | ||||||
|  | .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%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .el-calendar-table td { | ||||||
|  |   padding: 2px; | ||||||
|  |   vertical-align: top; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .el-calendar-day { | ||||||
|  |   height: 120px; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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> | ||||||
							
								
								
									
										672
									
								
								src/views/dhr_demo/xunjianjihua.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										672
									
								
								src/views/dhr_demo/xunjianjihua.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,672 @@ | |||||||
|  | <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">试验管理</div> | ||||||
|  |       <div class="nav-tab">报修管理</div> | ||||||
|  |       <div class="nav-tab">抢修管理</div> | ||||||
|  |       <div class="nav-tab">工单管理</div> | ||||||
|  |     </div> | ||||||
|  |     <div style="display: flex; align-items: center; gap: 1200px"> | ||||||
|  |       <TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent> | ||||||
|  |       <div style="display: flex; align-items: center; gap: 10px"> | ||||||
|  |         <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">搜索</el-button> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- 主内容区 --> | ||||||
|  |     <div class="grid grid-cols-1 lg:grid-cols-3 gap-6" style="grid-auto-rows: 1fr"> | ||||||
|  |       <!-- 左侧和中间内容区 --> | ||||||
|  |       <div class="lg:col-span-2 space-y-6"> | ||||||
|  |         <!-- 巡检记录与报告卡片 --> | ||||||
|  |         <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">42</p> | ||||||
|  |               </div> | ||||||
|  |               <div class="stat-card"> | ||||||
|  |                 <p class="stat-label">发现问题数</p> | ||||||
|  |                 <p class="stat-value">7</p> | ||||||
|  |               </div> | ||||||
|  |               <div class="stat-card"> | ||||||
|  |                 <p class="stat-label">已解决问题</p> | ||||||
|  |                 <p class="stat-value">5</p> | ||||||
|  |               </div> | ||||||
|  |               <div class="stat-card"> | ||||||
|  |                 <p class="stat-label">平均完成时间</p> | ||||||
|  |                 <p class="stat-value">45分钟</p> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |             <div class="divider"></div> | ||||||
|  |  | ||||||
|  |             <!-- 图表区域 --> | ||||||
|  |             <div class="grid grid-cols-1 md:grid-cols-3 gap-6 py-4"> | ||||||
|  |               <!-- 饼图 - 本月巡检完成情况 --> | ||||||
|  |               <div class="md:col-span-1"> | ||||||
|  |                 <p class="chart-title">本月完成巡检</p> | ||||||
|  |                 <div class="relative w-32 h-32 mx-auto"> | ||||||
|  |                   <!-- 饼图使用SVG绘制 - 显示本月巡检完成情况 --> | ||||||
|  |                   <svg class="w-full h-full" viewBox="0 0 100 100"> | ||||||
|  |                     <!-- 背景圆环 --> | ||||||
|  |                     <circle cx="50" cy="50" r="45" fill="none" stroke="#f3f4f6" stroke-width="10" /> | ||||||
|  |                     <!-- 已完成部分 (72%) --> | ||||||
|  |                     <circle | ||||||
|  |                       cx="50" | ||||||
|  |                       cy="50" | ||||||
|  |                       r="45" | ||||||
|  |                       fill="none" | ||||||
|  |                       stroke="#10b981" | ||||||
|  |                       stroke-width="10" | ||||||
|  |                       stroke-dasharray="282.74" | ||||||
|  |                       stroke-dashoffset="113.1" | ||||||
|  |                       transform="rotate(-90 50 50)" | ||||||
|  |                     /> | ||||||
|  |                     <!-- 未完成部分 (28%) --> | ||||||
|  |                     <circle | ||||||
|  |                       cx="50" | ||||||
|  |                       cy="50" | ||||||
|  |                       r="45" | ||||||
|  |                       fill="none" | ||||||
|  |                       stroke="#f97316" | ||||||
|  |                       stroke-width="10" | ||||||
|  |                       stroke-dasharray="113.1" | ||||||
|  |                       stroke-dashoffset="0" | ||||||
|  |                       transform="rotate(-90 50 50)" | ||||||
|  |                     /> | ||||||
|  |                   </svg> | ||||||
|  |                   <!-- 饼图中心显示 --> | ||||||
|  |                   <div class="absolute inset-0 flex flex-col items-center justify-center"> | ||||||
|  |                     <p class="text-sm text-gray-500">已解决问题</p> | ||||||
|  |                     <p class="text-lg font-bold text-gray-800">72%</p> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- 饼图图例 --> | ||||||
|  |                 <div class="mt-3 flex justify-center space-x-4"> | ||||||
|  |                   <div class="flex items-center"> | ||||||
|  |                     <div class="w-3 h-3 rounded-full bg-green-500 mr-1"></div> | ||||||
|  |                     <span class="text-xs text-gray-600">已解决</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="flex items-center"> | ||||||
|  |                     <div class="w-3 h-3 rounded-full bg-orange-500 mr-1"></div> | ||||||
|  |                     <span class="text-xs text-gray-600">未解决</span> | ||||||
|  |                   </div> | ||||||
|  |                 </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">68%</span> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                       <div class="bg-red-500 h-2 rounded-full" style="width: 68%"></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">72%</span> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                       <div class="bg-green-500 h-2 rounded-full" style="width: 72%"></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">60%</span> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                       <div class="bg-gray-500 h-2 rounded-full" style="width: 60%"></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">85%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                     <div class="bg-blue-500 h-2 rounded-full" style="width: 85%"></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">内存使用率</span> | ||||||
|  |                     <span class="text-gray-500">62%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                     <div class="bg-blue-500 h-2 rounded-full" style="width: 62%"></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">45%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                     <div class="bg-blue-500 h-2 rounded-full" style="width: 45%"></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">响应时间</span> | ||||||
|  |                     <span class="text-gray-500">30%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                     <div class="bg-blue-500 h-2 rounded-full" style="width: 30%"></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div class="flex justify-between text-sm mb-1"> | ||||||
|  |                     <span class="text-gray-600">磁盘空间状态</span> | ||||||
|  |                     <span class="text-gray-500">15%</span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="w-full bg-gray-200 rounded-full h-2"> | ||||||
|  |                     <div class="bg-blue-500 h-2 rounded-full" style="width: 15%"></div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <!-- 右侧最近巡检结果 --> | ||||||
|  |       <div class="lg:col-span-1" style="display: flex; flex-direction: column; height: 100%"> | ||||||
|  |         <div class="content-card" style="flex: 1; display: flex; flex-direction: column"> | ||||||
|  |           <div class="card-header"> | ||||||
|  |             <h2 class="card-title">最近巡检结果</h2> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <!-- 巡检结果列表 --> | ||||||
|  |           <div class="card-body" style="flex: 1; overflow-y: auto"> | ||||||
|  |             <div class="inspection-results space-y-4"> | ||||||
|  |               <!-- 结果1:正常 --> | ||||||
|  |               <div class="inspection-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm"> | ||||||
|  |                 <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<500</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"> | ||||||
|  |                 <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"> | ||||||
|  |                 <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 } from 'vue'; | ||||||
|  | import router from '@/router'; | ||||||
|  | import TitleComponent from '@/views/demo/components/TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const filterStatus = ref('all'); | ||||||
|  | const filterType = ref('all'); | ||||||
|  | const dateRange = ref([]); | ||||||
|  |  | ||||||
|  | // 时间范围选择 | ||||||
|  | const timeRange = ref('month'); // 默认选中"月" | ||||||
|  |  | ||||||
|  | // 时间范围切换函数 | ||||||
|  | const handleTimeRangeChange = (range) => { | ||||||
|  |   timeRange.value = range; | ||||||
|  |   // 在实际应用中,这里应该根据选择的时间范围重新获取数据 | ||||||
|  |   console.log(`切换到${range}视图`); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 导航方法 | ||||||
|  | const handleInspection1 = () => { | ||||||
|  |   router.push('/rili/rili'); | ||||||
|  | }; | ||||||
|  | const handleInspection2 = () => { | ||||||
|  |   router.push('/rili/InspectionManagement'); | ||||||
|  | }; | ||||||
|  | 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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 内容卡片样式 */ | ||||||
|  | .content-card { | ||||||
|  |   background-color: #fff; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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: 0 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 统计卡片样式 */ | ||||||
|  | .stat-card { | ||||||
|  |   background-color: #f5f7fa; | ||||||
|  |   border-radius: 6px; | ||||||
|  |   padding: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 区域标题 */ | ||||||
|  | .section-title { | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0 0 12px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 记录列表样式 */ | ||||||
|  | .record-list { | ||||||
|  |   margin: 0; | ||||||
|  |   padding: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-item { | ||||||
|  |   padding: 16px 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-title { | ||||||
|  |   font-size: 14px; | ||||||
|  |   font-weight: 500; | ||||||
|  |   color: #303133; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .record-time, | ||||||
|  | .record-type { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #909399; | ||||||
|  |   margin: 4px 0 0 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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 操作按钮 */ | ||||||
|  | .action-btn { | ||||||
|  |   color: #409eff; | ||||||
|  |   font-size: 12px; | ||||||
|  |   padding: 4px 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .action-btn:hover { | ||||||
|  |   color: #66b1ff; | ||||||
|  |   background-color: #ecf5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @media (max-width: 1200px) { | ||||||
|  |   .filter-bar { | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: stretch; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .filter-actions { | ||||||
|  |     margin-left: 0; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										892
									
								
								src/views/dhr_demo/xunjianrenwu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										892
									
								
								src/views/dhr_demo/xunjianrenwu.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,892 @@ | |||||||
|  | <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">试验管理</div> | ||||||
|  |         <div class="nav-tab">报修管理</div> | ||||||
|  |         <div class="nav-tab">抢修管理</div> | ||||||
|  |         <div class="nav-tab">工单管理</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" @click="handleSearch"> <i class="el-icon-search mr-1"></i>搜索 </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"> | ||||||
|  |           <div class="task-header"> | ||||||
|  |             <div class="task-title"> | ||||||
|  |               {{ task.title }} | ||||||
|  |             </div> | ||||||
|  |             <div class="task-status" :class="task.statusClass"> | ||||||
|  |               {{ 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" size="small" class="action-btn view-btn" @click="handleView(task)"> 详情 </el-button> | ||||||
|  |             <el-button type="primary" size="small" :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 '@/views/demo/components/TitleComponent.vue'; | ||||||
|  |  | ||||||
|  | // 激活的选项卡 | ||||||
|  | const activeTab = ref('task'); | ||||||
|  |  | ||||||
|  | // 筛选条件 | ||||||
|  | const taskStatus = ref(''); | ||||||
|  | const planType = ref(''); | ||||||
|  | const executor = ref(''); | ||||||
|  |  | ||||||
|  | // 任务数据 | ||||||
|  | const tasks = ref([ | ||||||
|  |   { | ||||||
|  |     title: '生产服务器日常巡检', | ||||||
|  |     status: 'pending', | ||||||
|  |     statusText: '待执行', | ||||||
|  |     statusClass: 'status-pending', | ||||||
|  |     planTime: '2025-06-16 08:30', | ||||||
|  |     target: '生产服务器集群(12台)', | ||||||
|  |     executor: '张明', | ||||||
|  |     relatedPlan: '每日巡检计划', | ||||||
|  |     actionText: '开始执行', | ||||||
|  |     actionClass: 'start-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '机房环境检查', | ||||||
|  |     status: 'delayed', | ||||||
|  |     statusText: '已延期', | ||||||
|  |     statusClass: 'status-delayed', | ||||||
|  |     planTime: '2025-06-16 08:30', | ||||||
|  |     target: '机房温度、湿度、电源', | ||||||
|  |     executor: '李华', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     delayReason: '设备维修处理中', | ||||||
|  |     actionText: '重新安排', | ||||||
|  |     actionClass: 'reschedule-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '网络设备安全巡检', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '执行中', | ||||||
|  |     statusClass: 'status-executing', | ||||||
|  |     planTime: '2025-06-16 09:30', | ||||||
|  |     target: '核心交换机、防火墙', | ||||||
|  |     executor: '王强', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     progress: 60, | ||||||
|  |     progressColor: '#FF7D00', | ||||||
|  |     actionText: '完成', | ||||||
|  |     actionClass: 'complete-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '数据库性能巡检', | ||||||
|  |     status: 'completed', | ||||||
|  |     statusText: '已完成', | ||||||
|  |     statusClass: 'status-completed', | ||||||
|  |     planTime: '2025-06-16 10:30', | ||||||
|  |     target: '生产数据库集群(2组)', | ||||||
|  |     executor: '赵伟', | ||||||
|  |     relatedPlan: '每月巡检计划', | ||||||
|  |     result: '正常', | ||||||
|  |     resultClass: 'result-normal', | ||||||
|  |     actionText: '查看报告', | ||||||
|  |     actionClass: 'report-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '生产服务器日常巡检', | ||||||
|  |     status: 'pending', | ||||||
|  |     statusText: '待执行', | ||||||
|  |     statusClass: 'status-pending', | ||||||
|  |     planTime: '2025-06-16 13:30', | ||||||
|  |     target: '生产服务器集群(12台)', | ||||||
|  |     executor: '张明', | ||||||
|  |     relatedPlan: '每日巡检计划', | ||||||
|  |     actionText: '开始执行', | ||||||
|  |     actionClass: 'start-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '机房环境检查', | ||||||
|  |     status: 'delayed', | ||||||
|  |     statusText: '已延期', | ||||||
|  |     statusClass: 'status-delayed', | ||||||
|  |     planTime: '2025-06-16 14:00', | ||||||
|  |     target: '机房温度、湿度、电源', | ||||||
|  |     executor: '李华', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     delayReason: '设备维修处理中', | ||||||
|  |     actionText: '重新安排', | ||||||
|  |     actionClass: 'reschedule-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '网络设备安全巡检', | ||||||
|  |     status: 'executing', | ||||||
|  |     statusText: '执行中', | ||||||
|  |     statusClass: 'status-executing', | ||||||
|  |     planTime: '2025-06-16 15:00', | ||||||
|  |     target: '核心交换机、防火墙', | ||||||
|  |     executor: '王强', | ||||||
|  |     relatedPlan: '每周巡检计划', | ||||||
|  |     progress: 35, | ||||||
|  |     progressColor: '#FF7D00', | ||||||
|  |     actionText: '完成', | ||||||
|  |     actionClass: 'complete-btn' | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '数据库性能巡检', | ||||||
|  |     status: 'completed', | ||||||
|  |     statusText: '已完成', | ||||||
|  |     statusClass: 'status-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'); | ||||||
|  | }; | ||||||
|  | </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); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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; | ||||||
|  |   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-bar .el-select .el-input__inner { | ||||||
|  |   border-radius: 4px; | ||||||
|  |   border-color: #dcdfe6; | ||||||
|  |   transition: all 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .filter-bar .el-select .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 任务卡片样式 */ | ||||||
|  | .task-cards { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: repeat(auto-fill, minmax(300px, 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 16px; /* 底部留出更多空间给按钮 */ | ||||||
|  |   transition: box-shadow 0.2s ease; | ||||||
|  |   position: relative; | ||||||
|  |   overflow: hidden; | ||||||
|  |   min-height: 280px; /* 确保有足够高度显示所有内容 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card::before { | ||||||
|  |   content: ''; | ||||||
|  |   position: absolute; | ||||||
|  |   left: 0; | ||||||
|  |   top: 0; | ||||||
|  |   bottom: 0; | ||||||
|  |   width: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card.status-pending::before { | ||||||
|  |   background-color: #1677ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card.status-delayed::before { | ||||||
|  |   background-color: #ff4d4f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card.status-executing::before { | ||||||
|  |   background-color: #fa8c16; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card.status-completed::before { | ||||||
|  |   background-color: #52c41a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .task-card:hover { | ||||||
|  |   transform: translateY(-3px); | ||||||
|  |   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 待执行状态 - 蓝色 */ | ||||||
|  | .status-pending { | ||||||
|  |   background-color: #e6f7ff; | ||||||
|  |   color: #1677ff; | ||||||
|  |   border-color: #91d5ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 已延期状态 - 红色 */ | ||||||
|  | .status-delayed { | ||||||
|  |   background-color: #fff2f0; | ||||||
|  |   color: #ff4d4f; | ||||||
|  |   border-color: #ffccc7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 执行中状态 - 黄色 */ | ||||||
|  | .status-executing { | ||||||
|  |   background-color: #fffbe6; | ||||||
|  |   color: #fa8c16; | ||||||
|  |   border-color: #ffe58f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 已完成状态 - 绿色 */ | ||||||
|  | .status-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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress-text { | ||||||
|  |   position: absolute; | ||||||
|  |   right: 0; | ||||||
|  |   top: 0; | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .view-btn:hover { | ||||||
|  |   color: #0e42d2; | ||||||
|  |   background-color: #e8f3ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .start-btn { | ||||||
|  |   background-color: #165dff; | ||||||
|  |   border-color: #165dff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .start-btn:hover { | ||||||
|  |   background-color: #0e42d2; | ||||||
|  |   border-color: #0e42d2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .reschedule-btn { | ||||||
|  |   background-color: #ff7d00; | ||||||
|  |   border-color: #ff7d00; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .reschedule-btn:hover { | ||||||
|  |   background-color: #e86a00; | ||||||
|  |   border-color: #e86a00; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .complete-btn { | ||||||
|  |   background-color: #00b42a; | ||||||
|  |   border-color: #00b42a; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .complete-btn:hover { | ||||||
|  |   background-color: #008718; | ||||||
|  |   border-color: #008718; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .report-btn { | ||||||
|  |   background-color: #86909c; | ||||||
|  |   border-color: #86909c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .report-btn:hover { | ||||||
|  |   background-color: #6b7785; | ||||||
|  |   border-color: #6b7785; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 分页区域样式 */ | ||||||
|  | .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 响应式设计 */ | ||||||
|  | @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; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | /* 导航栏样式 */ | ||||||
|  | .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; | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @ -1,7 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="leftPage"> |   <div class="leftPage"> | ||||||
|     <div class="topPage"> |     <div class="topPage"> | ||||||
|       <Title style="font-size: 22px" title="企业关键指标" /> |       <Title title="企业关键指标" /> | ||||||
|       <div class="indicators"> |       <div class="indicators"> | ||||||
|         <div class="indicator-card" v-for="indicator in indicators" :key="indicator.id"> |         <div class="indicator-card" v-for="indicator in indicators" :key="indicator.id"> | ||||||
|           <div style="display: flex; align-items: baseline; gap: 4px; margin-bottom: 5px"> |           <div style="display: flex; align-items: baseline; gap: 4px; margin-bottom: 5px"> | ||||||
| @ -17,7 +17,7 @@ | |||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <div class="endPage"> |     <div class="endPage"> | ||||||
|       <Title style="font-size: 22px" title="人员情况" /> |       <Title title="人员情况" /> | ||||||
|       <!-- 人员总览区域 --> |       <!-- 人员总览区域 --> | ||||||
|       <div class="people_overview"> |       <div class="people_overview"> | ||||||
|         <div class="people_overview_content"> |         <div class="people_overview_content"> | ||||||
| @ -80,7 +80,7 @@ | |||||||
|  |  | ||||||
|       <!-- 项目出勤率柱状图 --> |       <!-- 项目出勤率柱状图 --> | ||||||
|       <div class="project_attendance_chart"> |       <div class="project_attendance_chart"> | ||||||
|         <Title style="font-size: 22px" title="项目出勤率统计" /> |         <Title title="项目出勤率统计" /> | ||||||
|  |  | ||||||
|         <div class="chart_content" ref="attendanceChartRef"></div> |         <div class="chart_content" ref="attendanceChartRef"></div> | ||||||
|       </div> |       </div> | ||||||
| @ -108,31 +108,31 @@ const mapChartRef = ref<HTMLDivElement | null>(null); | |||||||
| const indicators = ref([ | const indicators = ref([ | ||||||
|   { |   { | ||||||
|     id: '1', |     id: '1', | ||||||
|     name: '在建项目', |     name: '光伏项目', | ||||||
|     value: '28', |     value: '28', | ||||||
|     unit: '个', |     unit: '个', | ||||||
|     iconPath: '/assets/demo/beUnder.png' |     iconPath: '/assets/demo/beUnder.png' | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     id: '2', |     id: '2', | ||||||
|     name: '合同总额', |     name: '风电项目', | ||||||
|     value: '288.88', |     value: '288.88', | ||||||
|     unit: '亿元', |     unit: '个', | ||||||
|     iconPath: '/assets/demo/contract.png' |     iconPath: '/src/assets/images/contract.png' | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     id: '3', |     id: '3', | ||||||
|     name: '总容量', |     name: '光伏系统总容量', | ||||||
|     value: '158.88', |     value: '158.88', | ||||||
|     unit: '个', |     unit: 'MW', | ||||||
|     iconPath: '/assets/demo/totalCapacity.png' |     iconPath: '/src/assets/images/totalCapacity.png' | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     id: '4', |     id: '4', | ||||||
|     name: '今日施工', |     name: '风电项目总容量', | ||||||
|     value: '18', |     value: '18', | ||||||
|     unit: '个', |     unit: 'MW', | ||||||
|     iconPath: '/assets/demo/todayConstruction.png' |     iconPath: '/src/assets/images/todayConstruction.png' | ||||||
|   } |   } | ||||||
| ]); | ]); | ||||||
|  |  | ||||||
| @ -255,7 +255,7 @@ const scrollToProject = (index: number) => { | |||||||
|     // 计算滚动条应该移动到的位置 |     // 计算滚动条应该移动到的位置 | ||||||
|     // 确保当前项目居中显示 |     // 确保当前项目居中显示 | ||||||
|     const totalProjects = projectAttendanceData.value.length; |     const totalProjects = projectAttendanceData.value.length; | ||||||
|     const visiblePercentage = 15; // 与dataZoom的end值保持一致 |     const visiblePercentage = 20; // 与dataZoom的end值保持一致 | ||||||
|     const itemPercentage = 100 / totalProjects; // 每个项目所占总宽度的百分比 |     const itemPercentage = 100 / totalProjects; // 每个项目所占总宽度的百分比 | ||||||
|  |  | ||||||
|     // 计算新的start值,使当前项目尽量居中显示 |     // 计算新的start值,使当前项目尽量居中显示 | ||||||
| @ -273,28 +273,6 @@ const scrollToProject = (index: number) => { | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * 开始自动滚动 |  | ||||||
|  */ |  | ||||||
| const startScroll = () => { |  | ||||||
|   if (scrollInterval.value) return; |  | ||||||
|  |  | ||||||
|   scrollInterval.value = window.setInterval(() => { |  | ||||||
|     currentScrollIndex.value++; |  | ||||||
|     scrollToProject(currentScrollIndex.value); |  | ||||||
|   }, scrollSpeed); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * 停止自动滚动 |  | ||||||
|  */ |  | ||||||
| const stopScroll = () => { |  | ||||||
|   if (scrollInterval.value) { |  | ||||||
|     clearInterval(scrollInterval.value); |  | ||||||
|     scrollInterval.value = null; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 获取项目出勤率统计数据 - 保持项目出勤率图表功能 |  * 获取项目出勤率统计数据 - 保持项目出勤率图表功能 | ||||||
|  */ |  */ | ||||||
| @ -367,10 +345,10 @@ const getKeyIndexData = async () => { | |||||||
|   const { data, code } = res; |   const { data, code } = res; | ||||||
|   if (code === 200) { |   if (code === 200) { | ||||||
|     // 更新指标数据,使用接口返回的指定字段 |     // 更新指标数据,使用接口返回的指定字段 | ||||||
|     indicators.value[0].value = data.ongoingProject || 0; |     indicators.value[0].value = data.photovoltaicCount || 0; | ||||||
|     indicators.value[1].value = data.totalContractAmount || 0; |     indicators.value[1].value = data.windElectricityCount || 0; | ||||||
|     indicators.value[2].value = data.totalCapacity || 0; |     indicators.value[2].value = data.photovoltaicTotalCapacity || 0; | ||||||
|     indicators.value[3].value = data.todayProject || 0; |     indicators.value[3].value = data.windElectricityTotalCapacity || 0; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @ -593,17 +571,9 @@ const initAttendanceChart = () => { | |||||||
|  |  | ||||||
|   attendanceChart.setOption(option); |   attendanceChart.setOption(option); | ||||||
|  |  | ||||||
|   // 添加鼠标悬浮事件监听 |   // 移除自动滚动功能,保留其他事件监听 | ||||||
|   if (attendanceChartRef.value) { |   if (attendanceChartRef.value) { | ||||||
|     // 鼠标进入图表区域时停止滚动 |     // 保留其他可能需要的事件监听器 | ||||||
|     attendanceChartRef.value.addEventListener('mouseenter', () => { |  | ||||||
|       stopScroll(); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // 鼠标离开图表区域时重新开始滚动 |  | ||||||
|     attendanceChartRef.value.addEventListener('mouseleave', () => { |  | ||||||
|       startScroll(); |  | ||||||
|     }); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // 添加窗口大小变化时的图表更新 |   // 添加窗口大小变化时的图表更新 | ||||||
| @ -619,11 +589,7 @@ const initAttendanceChart = () => { | |||||||
|   onUnmounted(() => { |   onUnmounted(() => { | ||||||
|     window.removeEventListener('resize', handleResize); |     window.removeEventListener('resize', handleResize); | ||||||
|  |  | ||||||
|     // 移除鼠标事件监听 |     // 移除鼠标事件监听(已在上面移除添加的事件监听) | ||||||
|     if (attendanceChartRef.value) { |  | ||||||
|       attendanceChartRef.value.removeEventListener('mouseenter', stopScroll); |  | ||||||
|       attendanceChartRef.value.removeEventListener('mouseleave', startScroll); |  | ||||||
|     } |  | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @ -652,9 +618,6 @@ onMounted(async () => { | |||||||
|  |  | ||||||
|   // 再初始化图表 |   // 再初始化图表 | ||||||
|   initAttendanceChart(); |   initAttendanceChart(); | ||||||
|  |  | ||||||
|   // 图表初始化后自动开始滚动 |  | ||||||
|   startScroll(); |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
| onUnmounted(() => { | onUnmounted(() => { | ||||||
| @ -667,9 +630,6 @@ onUnmounted(() => { | |||||||
|     attendanceChart.dispose(); |     attendanceChart.dispose(); | ||||||
|     attendanceChart = null; |     attendanceChart = null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // 清理滚动计时器 |  | ||||||
|   stopScroll(); |  | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| @ -879,10 +839,8 @@ onUnmounted(() => { | |||||||
|   text-shadow: 0px 1.24px 6.21px rgba(0, 200, 83, 0.5); |   text-shadow: 0px 1.24px 6.21px rgba(0, 200, 83, 0.5); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* 点阵地图样式 */ |  | ||||||
| .people_map { | .people_map { | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   height: 120px; |  | ||||||
|   margin-top: 8px; |   margin-top: 8px; | ||||||
|   background: rgba(10, 24, 45, 0.5); |   background: rgba(10, 24, 45, 0.5); | ||||||
|   border: 1px solid rgba(29, 214, 255, 0.1); |   border: 1px solid rgba(29, 214, 255, 0.1); | ||||||
|  | |||||||
| @ -71,15 +71,17 @@ let data = [ | |||||||
| const getTrajectoryData = async () => { | const getTrajectoryData = async () => { | ||||||
|   try { |   try { | ||||||
|     // 从URL参数中获取clientId、projectId和userId |     // 从URL参数中获取clientId、projectId和userId | ||||||
|     const { clientId, projectId, userId } = route.query; |     const { clientId, projectId, userId, gpsType } = route.query; | ||||||
|  |  | ||||||
|     if (!clientId || !projectId || !userId) { |     if (!projectId || !userId || !gpsType) { | ||||||
|       ElMessage.warning('缺少必要参数,请检查传入的参数'); |       ElMessage.warning('缺少必要参数,请检查传入的参数'); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     loading.value = true; |     loading.value = true; | ||||||
|     const res = await getFootNote({ clientId, projectId, userId }); |     // 确保gpsType转换为数字类型,以便正确传递给后端 | ||||||
|  |     const gpsTypeNum = parseInt(gpsType, 10); | ||||||
|  |     const res = await getFootNote({ clientId, projectId, userId, gpsType: gpsTypeNum }); | ||||||
|  |  | ||||||
|     if (res && res.code === 200 && res.data && res.data.length > 0) { |     if (res && res.code === 200 && res.data && res.data.length > 0) { | ||||||
|       data = res.data; |       data = res.data; | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ | |||||||
|  |  | ||||||
|     <el-card shadow="never"> |     <el-card shadow="never"> | ||||||
|       <template #header> |       <template #header> | ||||||
|         <el-row :gutter="10" class="mb8"> |         <el-row :gutter="20" class="mb8"> | ||||||
|           <el-col :span="1.5"> |           <el-col :span="1.5"> | ||||||
|             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['gps:equipment:edit']" |             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['gps:equipment:edit']" | ||||||
|               >修改</el-button |               >修改</el-button | ||||||
| @ -39,7 +39,12 @@ | |||||||
|             > |             > | ||||||
|           </el-col> |           </el-col> | ||||||
|           <el-col :span="2"> |           <el-col :span="2"> | ||||||
|             <el-button type="primary" plain @click="handleViewAll">{{ viewAllButtonText }}</el-button> |             <el-button type="primary" plain @click="toggleGpsType"> | ||||||
|  |               {{ currentGpsType === 0 ? '显示用户数据' : '显示设备数据' }} | ||||||
|  |             </el-button> | ||||||
|  |           </el-col> | ||||||
|  |           <el-col :span="2"> | ||||||
|  |             <el-button type="primary" v-if="queryParams.gpsType !== 1" plain @click="handleViewAll">{{ viewAllButtonText }}</el-button> | ||||||
|           </el-col> |           </el-col> | ||||||
|  |  | ||||||
|           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> | ||||||
| @ -102,7 +107,7 @@ | |||||||
|                 type="primary" |                 type="primary" | ||||||
|                 icon="Location" |                 icon="Location" | ||||||
|                 v-hasPermi="['gps:equipmentSon:getList']" |                 v-hasPermi="['gps:equipmentSon:getList']" | ||||||
|                 @click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, scope.row.clientId)" |                 @click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, scope.row.clientId, scope.row.gpsType)" | ||||||
|                 :disabled="!scope.row.userId || !scope.row.projectId" |                 :disabled="!scope.row.userId || !scope.row.projectId" | ||||||
|               ></el-button> |               ></el-button> | ||||||
|             </el-tooltip> |             </el-tooltip> | ||||||
| @ -189,7 +194,7 @@ | |||||||
|                   type="primary" |                   type="primary" | ||||||
|                   icon="Location" |                   icon="Location" | ||||||
|                   v-hasPermi="['gps:equipmentSon:getList']" |                   v-hasPermi="['gps:equipmentSon:getList']" | ||||||
|                   @click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, currentHistoryClientId)" |                   @click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, currentHistoryClientId, currentGpsType)" | ||||||
|                 ></el-button> |                 ></el-button> | ||||||
|               </el-tooltip> |               </el-tooltip> | ||||||
|             </template> |             </template> | ||||||
| @ -301,6 +306,9 @@ const initFormData: EquipmentForm = { | |||||||
|   remark: undefined |   remark: undefined | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | // 当前GPS类型 (0:设备数据, 1:用户数据) | ||||||
|  | const currentGpsType = ref(0); | ||||||
|  |  | ||||||
| // 页面数据 | // 页面数据 | ||||||
| const data = reactive<PageData<EquipmentForm, EquipmentQuery>>({ | const data = reactive<PageData<EquipmentForm, EquipmentQuery>>({ | ||||||
|   form: { ...initFormData }, |   form: { ...initFormData }, | ||||||
| @ -317,6 +325,7 @@ const data = reactive<PageData<EquipmentForm, EquipmentQuery>>({ | |||||||
|     creationTime: undefined, |     creationTime: undefined, | ||||||
|     lastAccessedTime: undefined, |     lastAccessedTime: undefined, | ||||||
|     registered: undefined, |     registered: undefined, | ||||||
|  |     gpsType: 0, // 默认显示设备数据 | ||||||
|     params: {} |     params: {} | ||||||
|   }, |   }, | ||||||
|   rules: { |   rules: { | ||||||
| @ -385,6 +394,15 @@ const formatDateTime = (timestamp: any): string => { | |||||||
|   return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |   return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /** 切换GPS数据类型 */ | ||||||
|  | const toggleGpsType = () => { | ||||||
|  |   currentGpsType.value = currentGpsType.value === 0 ? 1 : 0; | ||||||
|  |   queryParams.value.gpsType = currentGpsType.value; | ||||||
|  |   queryParams.value.pageNum = 1; | ||||||
|  |   getList(); | ||||||
|  |   proxy?.$modal.msgSuccess(`已切换到${currentGpsType.value === 0 ? '设备数据' : '用户数据'}模式`); | ||||||
|  | }; | ||||||
|  |  | ||||||
| /** 获取设备列表 */ | /** 获取设备列表 */ | ||||||
| const getList = async () => { | const getList = async () => { | ||||||
|   loading.value = true; |   loading.value = true; | ||||||
| @ -397,6 +415,9 @@ const getList = async () => { | |||||||
|       queryParams.value.projectId = undefined; |       queryParams.value.projectId = undefined; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // 确保gpsType参数正确设置 | ||||||
|  |     queryParams.value.gpsType = currentGpsType.value; | ||||||
|  |  | ||||||
|     const res = await listEquipment(queryParams.value); |     const res = await listEquipment(queryParams.value); | ||||||
|     equipmentList.value = res.rows as ExtendedEquipmentVO[]; |     equipmentList.value = res.rows as ExtendedEquipmentVO[]; | ||||||
|     total.value = res.total; |     total.value = res.total; | ||||||
| @ -490,16 +511,24 @@ const handleViewAll = () => { | |||||||
|   getList(); |   getList(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const handleGoToEmptyPage = (userId: any, projectId: any, clientId: any) => { | const handleGoToEmptyPage = (userId: any, projectId: any, clientId: any, gpsType: number) => { | ||||||
|   console.log('userId:', userId, 'projectId:', projectId, 'clientId:', clientId); |   console.log('userId:', userId, 'projectId:', projectId, 'clientId:', clientId, 'gpsType:', gpsType); | ||||||
|  |  | ||||||
|  |   const queryParams: any = { | ||||||
|  |     userId: userId, | ||||||
|  |     projectId: projectId, | ||||||
|  |     gpsType: gpsType, | ||||||
|  |     clientId: clientId | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // 当gpsType为0时传入clientId,为1时不传入 | ||||||
|  |   if (gpsType === 1 && clientId) { | ||||||
|  |     queryParams.clientId = ''; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   router.push({ |   router.push({ | ||||||
|     path: './equipmentGPS', |     path: './equipmentGPS', | ||||||
|     query: { |     query: queryParams | ||||||
|       userId: userId, |  | ||||||
|       projectId: projectId, |  | ||||||
|       clientId: clientId |  | ||||||
|     } |  | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| ID<template> | <template> | ||||||
|   <div class="large-screen"> |   <div class="large-screen"> | ||||||
|     <Header /> |     <Header /> | ||||||
|     <div class="nav"> |     <div class="nav"> | ||||||
| @ -21,7 +21,6 @@ import leftPage from './components/leftPage.vue'; | |||||||
| import centerPage from './components/centerPage.vue'; | import centerPage from './components/centerPage.vue'; | ||||||
| import rightPage from './components/rightPage.vue'; | import rightPage from './components/rightPage.vue'; | ||||||
| // import '@/assets/styles/element.scss'; | // import '@/assets/styles/element.scss'; | ||||||
|  |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style scoped lang="scss"> | <style scoped lang="scss"> | ||||||
|  | |||||||
| @ -101,10 +101,10 @@ | |||||||
|  |  | ||||||
|         <el-table-column label="操作" align="center" fixed="right" width="200"> |         <el-table-column label="操作" align="center" fixed="right" width="200"> | ||||||
|           <template #default="scope"> |           <template #default="scope"> | ||||||
|             <!-- 查看子项按钮 --> |             <!-- 查看流转台账按钮 --> | ||||||
|             <el-tooltip content="查看子项" placement="top"> |             <el-tooltip content="查看流转台账" placement="top"> | ||||||
|               <el-button link type="primary" @click="handleViewSons(scope.row)" v-hasPermi="['land:landTransferLedger:childrenList']"> |               <el-button link type="primary" @click="handleViewSons(scope.row)" v-hasPermi="['land:landTransferLedger:childrenList']"> | ||||||
|                 查看子项 |                 查看流转台账 | ||||||
|               </el-button> |               </el-button> | ||||||
|             </el-tooltip> |             </el-tooltip> | ||||||
|             <el-tooltip content="删除" placement="top"> |             <el-tooltip content="删除" placement="top"> | ||||||
| @ -162,7 +162,7 @@ | |||||||
|           <el-row :gutter="10" class="mb8"> |           <el-row :gutter="10" class="mb8"> | ||||||
|             <el-col :span="1.5"> |             <el-col :span="1.5"> | ||||||
|               <el-button type="primary" plain icon="Plus" @click="handleAddSon" v-hasPermi="['land:landTransferLedger:childrenAdd']"> |               <el-button type="primary" plain icon="Plus" @click="handleAddSon" v-hasPermi="['land:landTransferLedger:childrenAdd']"> | ||||||
|                 新增子项 |                 新增流转台账 | ||||||
|               </el-button> |               </el-button> | ||||||
|             </el-col> |             </el-col> | ||||||
|           </el-row> |           </el-row> | ||||||
| @ -397,9 +397,7 @@ | |||||||
|       </el-form> |       </el-form> | ||||||
|       <template #footer> |       <template #footer> | ||||||
|         <div class="dialog-footer"> |         <div class="dialog-footer"> | ||||||
|           <el-button v-hasPermi="['land:landTransferLedger:addSon']" :loading="sonButtonLoading" type="primary" @click="submitSonForm" |           <el-button :loading="sonButtonLoading" type="primary" @click="submitSonForm">确 定</el-button> | ||||||
|             >确 定</el-button |  | ||||||
|           > |  | ||||||
|           <el-button @click="cancelSonForm">取 消</el-button> |           <el-button @click="cancelSonForm">取 消</el-button> | ||||||
|         </div> |         </div> | ||||||
|       </template> |       </template> | ||||||
| @ -1026,7 +1024,7 @@ const handleAdd = () => { | |||||||
|   dialog.visible = true; |   dialog.visible = true; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** 查看子项按钮操作(打开子项弹窗时) */ | /** 新增流转台账按钮操作(打开子项弹窗时) */ | ||||||
| const handleViewSons = async (row: LandTransferLedgerVO) => { | const handleViewSons = async (row: LandTransferLedgerVO) => { | ||||||
|   if (!row?.id) return; |   if (!row?.id) return; | ||||||
|  |  | ||||||
| @ -1093,7 +1091,7 @@ const handleAddSon = async () => { | |||||||
|   await getListRoad(); |   await getListRoad(); | ||||||
|  |  | ||||||
|   // 5. 打开弹窗 |   // 5. 打开弹窗 | ||||||
|   sonFormDialog.title = '添加子项(继承父项数据)'; |   sonFormDialog.title = '新增流转台账'; | ||||||
|   sonFormDialog.visible = true; |   sonFormDialog.visible = true; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | |||||||
| @ -2,13 +2,18 @@ | |||||||
|   <div class="leftPage"> |   <div class="leftPage"> | ||||||
|     <div class="topPage"> |     <div class="topPage"> | ||||||
|       <Title title="项目公告" /> |       <Title title="项目公告" /> | ||||||
|       <div class="content" ref="contentRef" id="event_scroll" @mouseenter="pauseScroll" @mouseleave="resumeScroll"> |       <div | ||||||
|         <div class="content_item" v-for="item in news" :key="item.id" @click="showNewsDetail(item)"> |         class="content" | ||||||
|           <img src="@/assets/projectLarge/round.svg" alt=""> |         ref="contentRef" | ||||||
|  |         id="event_scroll" | ||||||
|  |         @mouseenter.native="autoScrollTable(true, false)" | ||||||
|  |         @mouseleave.native="autoScrollTable(false, true)" | ||||||
|  |       > | ||||||
|  |         <div class="content_item" v-for="item in news" :key="item.id"> | ||||||
|  |           <img src="@/assets/projectLarge/round.svg" alt="" /> | ||||||
|           <div class="ellipsis"> |           <div class="ellipsis"> | ||||||
|             {{ item.title }} |             {{ item.title }} | ||||||
|             <span style="color: rgba(138, 149, 165, 1);">{{ item.id === newId ? '关闭' : |             <span @click="showNewsDetail(item)" style="color: rgba(138, 149, 165, 1)">{{ item.id === newId ? '关闭' : '查看' }}</span> | ||||||
|               '查看' }}</span> |  | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
| @ -18,40 +23,40 @@ | |||||||
|       <!-- <div class="detail_title">{{ newDetail.title }}</div> --> |       <!-- <div class="detail_title">{{ newDetail.title }}</div> --> | ||||||
|       <div class="detail_content" v-html="newDetail.content"></div> |       <div class="detail_content" v-html="newDetail.content"></div> | ||||||
|       <div class="close" @click="newId = ''"> |       <div class="close" @click="newId = ''"> | ||||||
|         <CircleClose style="width: 1.2em; height: 1.2em;" /> |         <CircleClose style="width: 1.2em; height: 1.2em" /> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <div class="endPage"> |     <div class="endPage"> | ||||||
|       <Title title="人员情况" /> |       <Title title="人员情况" /> | ||||||
|       <div class="map"> |       <div class="map"> | ||||||
|         <img src="@/assets/projectLarge/map.svg" alt=""> |         <img src="@/assets/projectLarge/map.svg" alt="" /> | ||||||
|         <!-- <div ref="mapChartRef"></div> --> |         <!-- <div ref="mapChartRef"></div> --> | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
|       <div class="attendance_tag"> |       <div class="attendance_tag"> | ||||||
|         <div class="tag_item"> |         <div class="tag_item"> | ||||||
|           <img src="@/assets/projectLarge/people.svg" alt=""> |           <img src="@/assets/projectLarge/people.svg" alt="" /> | ||||||
|           <div class="tag_title">出勤人</div> |           <div class="tag_title">出勤人</div> | ||||||
|           <div class="tag_info"> |           <div class="tag_info"> | ||||||
|             {{ attendanceCount }} |             {{ attendanceCount }} | ||||||
|             <span style="font-size: 14px;">人</span> |             <span style="font-size: 14px">人</span> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|         <div class="tag_item"> |         <div class="tag_item"> | ||||||
|           <img src="@/assets/projectLarge/people.svg" alt=""> |           <img src="@/assets/projectLarge/people.svg" alt="" /> | ||||||
|           <div class="tag_title">在岗人</div> |           <div class="tag_title">在岗人</div> | ||||||
|           <div class="tag_info"> |           <div class="tag_info"> | ||||||
|             {{ peopleCount }} |             {{ peopleCount }} | ||||||
|             <span style="font-size: 14px;">人</span> |             <span style="font-size: 14px">人</span> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|         <div class="tag_item"> |         <div class="tag_item"> | ||||||
|           <img src="@/assets/projectLarge/people.svg" alt=""> |           <img src="@/assets/projectLarge/people.svg" alt="" /> | ||||||
|           <div class="tag_title">出勤率</div> |           <div class="tag_title">出勤率</div> | ||||||
|           <div class="tag_info"> |           <div class="tag_info"> | ||||||
|             {{ attendanceRate }} |             {{ attendanceRate }} | ||||||
|             <span style="font-size: 14px;">%</span> |             <span style="font-size: 14px">%</span> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
| @ -65,8 +70,9 @@ | |||||||
|         </div> |         </div> | ||||||
|         <div v-for="item in teamAttendanceList" :key="item.id" class="attendance_item"> |         <div v-for="item in teamAttendanceList" :key="item.id" class="attendance_item"> | ||||||
|           <div class="attendance_item_title">{{ item.teamName }}</div> |           <div class="attendance_item_title">{{ item.teamName }}</div> | ||||||
|           <div class="attendance_item_number">{{ item.attendanceNumber }} <span class="subfont">人/{{ item.allNumber |           <div class="attendance_item_number"> | ||||||
|               }}</span></div> |             {{ item.attendanceNumber }} <span class="subfont">人/{{ item.allNumber }}</span> | ||||||
|  |           </div> | ||||||
|           <div class="attendance_item_rate">{{ item.attendanceRate }} %</div> |           <div class="attendance_item_rate">{{ item.attendanceRate }} %</div> | ||||||
|           <div class="attendance_item_date subfont">{{ item.attendanceTime }}</div> |           <div class="attendance_item_date subfont">{{ item.attendanceTime }}</div> | ||||||
|         </div> |         </div> | ||||||
| @ -76,71 +82,80 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { ref } from "vue" | import { ref } from 'vue'; | ||||||
| import Title from './title.vue' | import Title from './title.vue'; | ||||||
| import { getScreenNews, getScreenPeople } from '@/api/projectScreen'; | import { getScreenNews, getScreenPeople } from '@/api/projectScreen/index'; | ||||||
|  | import { mapOption } from './optionList'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   projectId: { |   projectId: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: '' |     default: '' | ||||||
|   } |   } | ||||||
| }) | }); | ||||||
|  |  | ||||||
|  | let mapChart = null; | ||||||
|  | const mapChartRef = ref<HTMLDivElement | null>(null); | ||||||
| const contentRef = ref<HTMLDivElement | null>(null); | const contentRef = ref<HTMLDivElement | null>(null); | ||||||
| const news = ref([]) | const news = ref([]); | ||||||
| const newDetail = ref({ | const newDetail = ref({ | ||||||
|   title: '', |   title: '', | ||||||
|   content: '' |   content: '' | ||||||
| }) | }); | ||||||
| const newId = ref('') | const newId = ref(''); | ||||||
| const attendanceCount = ref(0) | const attendanceCount = ref(0); | ||||||
| const attendanceRate = ref(0) | const attendanceRate = ref(0); | ||||||
| const peopleCount = ref(0) | const peopleCount = ref(0); | ||||||
| const teamAttendanceList = ref([ | const teamAttendanceList = ref([{ id: '', teamName: '', attendanceNumber: 0, allNumber: 0, attendanceRate: 0, attendanceTime: '' }]); | ||||||
|   { id: "", teamName: "", attendanceNumber: 0, allNumber: 0, attendanceRate: 0, attendanceTime: "" }, |  | ||||||
| ]) |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 显示新闻详情 |  * 显示新闻详情 | ||||||
|  */ |  */ | ||||||
| const showNewsDetail = (item: any) => { | const showNewsDetail = (item: any) => { | ||||||
|   if (newId.value === item.id) { |   if (newId.value === item.id) { | ||||||
|     newId.value = '' |     newId.value = ''; | ||||||
|     return |     return; | ||||||
|   } |   } | ||||||
|   newDetail.value = item |   newDetail.value = item; | ||||||
|   newId.value = item.id |   newId.value = item.id; | ||||||
| } | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 获取项目人员出勤数据 |  * 获取项目人员出勤数据 | ||||||
|  */ |  */ | ||||||
| const getPeopleData = async () => { | const getPeopleData = async () => { | ||||||
|   const res = await getScreenPeople(props.projectId); |   const res = await getScreenPeople(props.projectId); | ||||||
|   const { data, code } = res |   const { data, code } = res; | ||||||
|   if (code === 200) { |   if (code === 200) { | ||||||
|     attendanceCount.value = data.attendanceCount |     attendanceCount.value = data.attendanceCount; | ||||||
|     attendanceRate.value = data.attendanceRate |     attendanceRate.value = data.attendanceRate; | ||||||
|     peopleCount.value = data.peopleCount |     peopleCount.value = data.peopleCount; | ||||||
|     teamAttendanceList.value = data.teamAttendanceList |     teamAttendanceList.value = data.teamAttendanceList; | ||||||
|   } |   } | ||||||
| } | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 获取项目新闻数据 |  * 获取项目新闻数据 | ||||||
|  */ |  */ | ||||||
| const getNewsData = async () => { | const getNewsData = async () => { | ||||||
|   const res = await getScreenNews(props.projectId); |   const res = await getScreenNews(props.projectId); | ||||||
|   const { data, code } = res |   const { data, code } = res; | ||||||
|   if (code === 200) { |   if (code === 200) { | ||||||
|     news.value = data |     news.value = data; | ||||||
|     requestAnimationFrame((timestamp) => autoScrollTable(timestamp)); |     autoScrollTable(5); | ||||||
|   } |   } | ||||||
| } | }; | ||||||
|  |  | ||||||
| var lastTime = 0; | var lastTime = 0; | ||||||
| var scrolltimerTable = null | const state = reactive({ | ||||||
|  |   events: [], | ||||||
|  |   outputList: [], | ||||||
|  |   detialInfoShow: false, | ||||||
|  |   notShowPro: [{ id: 37 }, { id: 44 }, { id: 48 }], //模块内容区域不展示的项目(中煤科工 广东户用光伏项目 兴隆光伏) | ||||||
|  |   scrolltimerTable: null, | ||||||
|  |   flagPause: true //滚动继续滚动 | ||||||
|  | }); | ||||||
|  |  | ||||||
| const autoScrollTable = (time: number) => { | const autoScrollTable = (time: number) => { | ||||||
|   const divData = document.getElementById('event_scroll'); |   const divData = document.getElementById('event_scroll'); | ||||||
| @ -175,13 +190,14 @@ const resumeScroll = () => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
|   getPeopleData() |   // nextTick(() => { | ||||||
|   getNewsData() |   //   initMapChart(); | ||||||
| }) |   // }); | ||||||
|  |   getPeopleData(); | ||||||
| onUnmounted(() => { |   getNewsData(); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | onUnmounted(() => {}); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style scoped lang="scss"> | <style scoped lang="scss"> | ||||||
|  | |||||||
| @ -35,7 +35,9 @@ | |||||||
|             <el-button type="warning" plain icon="Upload" @click="handleImport" v-hasPermi="['supplierInput:supplierInput:import']">导入</el-button> |             <el-button type="warning" plain icon="Upload" @click="handleImport" v-hasPermi="['supplierInput:supplierInput:import']">导入</el-button> | ||||||
|           </el-col> |           </el-col> | ||||||
|           <el-col :span="1.5"> |           <el-col :span="1.5"> | ||||||
|             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplierInput:supplierInput:export']">导出模板</el-button> |             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplierInput:supplierInput:export']" | ||||||
|  |               >导出模板</el-button | ||||||
|  |             > | ||||||
|           </el-col> |           </el-col> | ||||||
|           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> | ||||||
|         </el-row> |         </el-row> | ||||||
| @ -703,7 +705,7 @@ const handleExport = () => { | |||||||
|   try { |   try { | ||||||
|     // 创建a标签并直接下载public目录下的静态文件 |     // 创建a标签并直接下载public目录下的静态文件 | ||||||
|     const link = document.createElement('a'); |     const link = document.createElement('a'); | ||||||
|     link.href = '/assets/files/供应商导入模板.xlsx'; // 使用public目录下现有的Excel文件作为模板 |     link.href = '/xx.xlsx'; | ||||||
|     link.download = '供应商导入模板.xlsx'; |     link.download = '供应商导入模板.xlsx'; | ||||||
|     document.body.appendChild(link); |     document.body.appendChild(link); | ||||||
|     link.click(); |     link.click(); | ||||||
| @ -746,7 +748,7 @@ const handleImport = () => { | |||||||
|         loading.value = true; |         loading.value = true; | ||||||
|         // 调用导入接口 |         // 调用导入接口 | ||||||
|         const res = await leadingIn(formData, queryParams.value.projectId); |         const res = await leadingIn(formData, queryParams.value.projectId); | ||||||
|         console.log("111111111111",queryParams.value.projectId); |         console.log('111111111111', queryParams.value.projectId); | ||||||
|  |  | ||||||
|         if (res.code === 200) { |         if (res.code === 200) { | ||||||
|           proxy?.$modal.msgSuccess('导入成功'); |           proxy?.$modal.msgSuccess('导入成功'); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user