Merge remote-tracking branch 'origin/dev' into dev

dev
Newek 11 months ago
commit d22de0b5d9
  1. 148
      ALOps_sys_backend/alops-admin/src/main/java/com/alops/web/controller/equManagement/EquBaseController.java
  2. 6
      ALOps_sys_backend/alops-admin/src/main/java/com/alops/web/controller/equManagement/EquManuController.java
  3. 21
      ALOps_sys_backend/alops-admin/src/main/java/com/alops/web/controller/equManagement/EquSupplierController.java
  4. 24
      ALOps_sys_backend/alops-admin/src/main/java/com/alops/web/controller/equManagement/ScheduleRulesController.java
  5. 36
      ALOps_sys_backend/alops-admin/src/main/java/com/alops/web/controller/exceptionController/AlertMessageController.java
  6. 7
      ALOps_sys_backend/alops-admin/src/main/java/com/alops/web/controller/exceptionController/AlertRuleController.java
  7. 41
      ALOps_sys_backend/alops-admin/src/main/java/com/alops/web/controller/exceptionController/equAssessment.java
  8. 4
      ALOps_sys_backend/alops-admin/src/main/resources/application-druid.yml
  9. 14
      ALOps_sys_backend/alops-chat/src/main/java/com/alops/chat/repository/UploadedFileRepository.java
  10. 2
      ALOps_sys_backend/alops-framework/src/main/java/com/alops/framework/web/service/SysLoginService.java
  11. 2
      ALOps_sys_backend/alops-framework/src/main/java/com/alops/framework/web/service/SysRegisterService.java
  12. 12
      ALOps_sys_backend/alops-system/pom.xml
  13. 6
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/AlertMessage.java
  14. 1
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/AlertRule.java
  15. 51
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/EquBase.java
  16. 2
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/EquInterface.java
  17. 4
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/EquManu.java
  18. 2
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/EquRouting.java
  19. 8
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/EquSupplier.java
  20. 5
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/EquVeneer.java
  21. 27
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/AlertStatisticDto.java
  22. 112
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/EquBaseAddDto.java
  23. 11
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/EquBaseQueryDto.java
  24. 22
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/EquMonitorHomeDto.java
  25. 17
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/EquSupplierAddDto.java
  26. 13
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/EquSupplierUpdateDto.java
  27. 22
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/LevelCountDto.java
  28. 8
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/MonitorHistoryDto.java
  29. 29
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/MonitorLastDto.java
  30. 14
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/MonitorListDto.java
  31. 5
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/MonitorStatisticDto.java
  32. 17
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/TypeCountDto.java
  33. 48
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/dto/equipmentAssessmentDto.java
  34. 75
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/vo/AlertRuleVo.java
  35. 45
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/vo/equipmentAssessmentVo.java
  36. 37
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/vo/homeEquAlertMessageVo.java
  37. 28
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/domain/vo/queryEquBaseVO.java
  38. 30
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/job/GatherJob.java
  39. 3
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/mapper/AlertMessageMapper.java
  40. 7
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/mapper/AlertRuleMapper.java
  41. 22
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/mapper/EquBaseMapper.java
  42. 2
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/mapper/ScheduleRulesMapper.java
  43. 3
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/IAlertMessageService.java
  44. 5
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/IAlertRuleService.java
  45. 11
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/IEquBaseService.java
  46. 12
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/IEquSupplierService.java
  47. 4
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/IScheduleRulesService.java
  48. 4
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/AlertLaunchServiceImpl.java
  49. 25
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/AlertMessageServiceImpl.java
  50. 19
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/AlertRuleServiceImpl.java
  51. 154
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/EquBaseServiceImpl.java
  52. 6
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/EquManuServiceImpl.java
  53. 44
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/EquSupplierServiceImpl.java
  54. 6
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/EquTypeServiceImpl.java
  55. 133
      ALOps_sys_backend/alops-system/src/main/java/com/alops/system/service/impl/ScheduleRulesServiceImpl.java
  56. 29
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/AlertMessageMapper.xml
  57. 55
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/AlertRuleMapper.xml
  58. 307
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/EquBaseMapper.xml
  59. 3
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/EquManuMapper.xml
  60. 29
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/EquSupplierMapper.xml
  61. 1
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/EquTypeMapper.xml
  62. 2
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/EquVlanMapper.xml
  63. 6
      ALOps_sys_backend/alops-system/src/main/resources/mapper/system/ScheduleRulesMapper.xml
  64. 1
      ALOps_sys_fe/alops-ui/public/index.html
  65. 58
      ALOps_sys_fe/alops-ui/src/api/QandA/Aiassistant.js
  66. 52
      ALOps_sys_fe/alops-ui/src/api/QandA/dict/data.js
  67. 60
      ALOps_sys_fe/alops-ui/src/api/QandA/dict/type.js
  68. 49
      ALOps_sys_fe/alops-ui/src/api/QandA/knowledge.js
  69. 30
      ALOps_sys_fe/alops-ui/src/api/device/deviceInformation.js
  70. 7
      ALOps_sys_fe/alops-ui/src/api/device/deviceManufacturer.js
  71. 7
      ALOps_sys_fe/alops-ui/src/api/device/deviceType.js
  72. 4
      ALOps_sys_fe/alops-ui/src/api/device/files.js
  73. 49
      ALOps_sys_fe/alops-ui/src/api/device/supplier.js
  74. 50
      ALOps_sys_fe/alops-ui/src/api/inMonitoring/devicesState.js
  75. 58
      ALOps_sys_fe/alops-ui/src/api/inMonitoring/message.js
  76. 58
      ALOps_sys_fe/alops-ui/src/api/inMonitoring/rules.js
  77. 92
      ALOps_sys_fe/alops-ui/src/api/index/index.js
  78. BIN
      ALOps_sys_fe/alops-ui/src/assets/images/profile.jpg
  79. 17
      ALOps_sys_fe/alops-ui/src/components/ImageUpload/index.vue
  80. 2
      ALOps_sys_fe/alops-ui/src/router/index.js
  81. 1
      ALOps_sys_fe/alops-ui/src/utils/request.js
  82. 8
      ALOps_sys_fe/alops-ui/src/utils/ruoyi.js
  83. 4
      ALOps_sys_fe/alops-ui/src/views/QandA/Aiassistant/index.vue
  84. 352
      ALOps_sys_fe/alops-ui/src/views/QandA/knowledge/index.vue
  85. 372
      ALOps_sys_fe/alops-ui/src/views/device/deviceInformation/index.vue
  86. 136
      ALOps_sys_fe/alops-ui/src/views/device/deviceManufacturer/index.vue
  87. 4
      ALOps_sys_fe/alops-ui/src/views/device/deviceSupplier/index.vue
  88. 236
      ALOps_sys_fe/alops-ui/src/views/device/deviceType/index.vue
  89. 315
      ALOps_sys_fe/alops-ui/src/views/device/files/index.vue
  90. 348
      ALOps_sys_fe/alops-ui/src/views/device/supplier/index.vue
  91. 4
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/assessment/index.vue
  92. 514
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/devicesState/cardItem.vue
  93. 839
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/devicesState/detail.vue
  94. 69
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/devicesState/history.vue
  95. 36
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/devicesState/index.vue
  96. 509
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/earlyWarning/index.vue
  97. 321
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/inMonitor/message/index.vue
  98. 445
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/inMonitor/rules/index.vue
  99. 308
      ALOps_sys_fe/alops-ui/src/views/index copy.vue
  100. 818
      ALOps_sys_fe/alops-ui/src/views/index.vue
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,7 +1,9 @@
package com.alops.web.controller.equManagement; package com.alops.web.controller.equManagement;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -14,6 +16,7 @@ import com.alops.common.enums.BusinessType;
import com.alops.common.utils.poi.ExcelUtil; import com.alops.common.utils.poi.ExcelUtil;
import com.alops.system.domain.EquBase; import com.alops.system.domain.EquBase;
import com.alops.system.domain.dto.EquBaseQueryDto; import com.alops.system.domain.dto.EquBaseQueryDto;
import com.alops.system.domain.dto.EquMonitorHomeDto;
import com.alops.system.domain.dto.MonitorListDto; import com.alops.system.domain.dto.MonitorListDto;
import com.alops.system.domain.dto.MonitorStatisticDto; import com.alops.system.domain.dto.MonitorStatisticDto;
import com.alops.system.domain.vo.EquMonitorVO; import com.alops.system.domain.vo.EquMonitorVO;
@ -48,9 +51,9 @@ public class EquBaseController extends BaseController
* 查询设备基本信息列表 * 查询设备基本信息列表
*/ */
@PreAuthorize("@ss.hasPermi('device:files:list')") @PreAuthorize("@ss.hasPermi('device:files:list')")
@PostMapping("/list") @GetMapping("/list")
@ApiOperation("查询多个设备信息") @ApiOperation("查询多个设备信息")
public TableDataInfo list(@RequestBody EquBaseQueryDto equBase) public TableDataInfo list( EquBaseQueryDto equBase)
{ {
startPage(); startPage();
List<queryEquBaseVO> list = equBaseService.selectEquBaseList(equBase); List<queryEquBaseVO> list = equBaseService.selectEquBaseList(equBase);
@ -58,15 +61,31 @@ public class EquBaseController extends BaseController
} }
/**查询设备监测信息列表(查询多台显示界面的单独信息)**/ /**查询设备监测信息列表(查询多台显示界面的单独信息)**/
/**
* 查询多台设备的最新监测信息
**/
@PreAuthorize("@ss.hasPermi('device:files:query')") @PreAuthorize("@ss.hasPermi('device:files:query')")
@GetMapping("/listMonitor") @GetMapping("/monitorpage")
@ApiOperation("查询设备监测信息列表(查询多台显示界面的单独信息)") @ApiOperation("分页查询多台设备的最新监测信息")
public AjaxResult listMonitorInfo(EquBaseQueryDto equBaseQueryDto) public TableDataInfo getMonitorList() {
{ startPage(); // 无参调用,自动获取 pageNum/pageSize
List<MonitorListDto> list = equBaseService.selectEquMonitorList(equBaseQueryDto); List<MonitorListDto> list = equBaseService.selectEquMonitorListPaged();
return AjaxResult.success("查询成功", list); return getDataTable(list); // 自动封装分页结果
} }
/**
* 首页展示查询每台设备的最新监测信息
*/
@PreAuthorize("@ss.hasPermi('device:files:query')")
@GetMapping("/monitorById")
@ApiOperation("首页展示:查询每台设备的最新监测信息")
public TableDataInfo getLatestEquMonitorList() {
startPage(); // 启用分页(如果首页不分页可删除)
List<EquMonitorHomeDto> list = equBaseService.selectLatestEquMonitorList();
return getDataTable(list);
}
/** /**
* 获取设备最新时间的历史监控信息 * 获取设备最新时间的历史监控信息
* @param id 查询对象包含设备ID开始时间和结束时间 * @param id 查询对象包含设备ID开始时间和结束时间
@ -80,6 +99,7 @@ public class EquBaseController extends BaseController
// 调用职责单一的 Service 方法 // 调用职责单一的 Service 方法
return success(equBaseService.selectLatestEquMonitorInfo(id)); return success(equBaseService.selectLatestEquMonitorInfo(id));
} }
/** /**
* 获取设备指定时间段内的历史监控信息 * 获取设备指定时间段内的历史监控信息
* @param equBaseQueryDto 查询对象包含设备ID开始时间和结束时间 * @param equBaseQueryDto 查询对象包含设备ID开始时间和结束时间
@ -101,9 +121,18 @@ public class EquBaseController extends BaseController
@ApiOperation("按设备类型分类统计设备信息") @ApiOperation("按设备类型分类统计设备信息")
public AjaxResult listMonitorInfoByType() { public AjaxResult listMonitorInfoByType() {
List<MonitorStatisticDto> list = equBaseService.selectEquStatisticByType(); List<MonitorStatisticDto> list = equBaseService.selectEquStatisticByType();
return AjaxResult.success("查询成功", list); // 获取总设备数
int totalCount = 0;
if (list != null) {
totalCount = list.stream().mapToInt(MonitorStatisticDto::getCount).sum();
}
Map<String, Object> result = new HashMap<>();
result.put("totalCount", totalCount);
result.put("list", list);
return AjaxResult.success("查询成功", result);
} }
/** /**
* 获取设备基本信息详细信息 * 获取设备基本信息详细信息
*/ */
@ -116,38 +145,35 @@ public class EquBaseController extends BaseController
} }
/** // /**
* 根据设备ID返回图片流 // * 根据设备ID返回图片流
* 前端直接 <img src="/equBase/image/{id}"> // * 前端直接 <img src="/equBase/image/{id}">
*/ // */
//
@PreAuthorize("@ss.hasPermi('device:files:queryimage')") // @PreAuthorize("@ss.hasPermi('device:files:queryimage')")
@GetMapping(value = "/queryimage/{id}") // @GetMapping(value = "/queryimage/{id}")
@ApiOperation("查询单个设备图片") // @ApiOperation("查询单个设备图片")
public void getImage(@PathVariable String id, HttpServletResponse response) throws IOException { // public void getImage(@PathVariable String id, HttpServletResponse response) throws IOException {
if (id instanceof String) { //
System.out.println("这是一个字符串"); // byte[] imgBytes = equBaseService.selectEquBaseImageById(id).getEquImage();
} //
//
// if (imgBytes != null && imgBytes.length > 0) {
byte[] imgBytes = equBaseService.selectEquBaseImageById(id).getEquImage(); // // 设置响应类型,可根据实际图片类型动态修改
// response.setContentType("image/png");
// // 可选:缓存图片
// response.setHeader("Cache-Control", "max-age=3600");
// // 输出流写入响应
// ServletOutputStream os = response.getOutputStream();
// os.write(imgBytes);
// os.flush();
// os.close();
// } else {
// // 图片不存在
// response.sendError(HttpServletResponse.SC_NOT_FOUND);
// }
// }
if (imgBytes != null && imgBytes.length > 0) {
// 设置响应类型,可根据实际图片类型动态修改
response.setContentType("image/png");
// 可选:缓存图片
response.setHeader("Cache-Control", "max-age=3600");
// 输出流写入响应
ServletOutputStream os = response.getOutputStream();
os.write(imgBytes);
os.flush();
os.close();
} else {
// 图片不存在
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
//厂商下拉表 //厂商下拉表
@PreAuthorize("@ss.hasPermi('device:files:queryManufacture')") @PreAuthorize("@ss.hasPermi('device:files:queryManufacture')")
@GetMapping( "/manufacture") @GetMapping( "/manufacture")
@ -181,46 +207,44 @@ public class EquBaseController extends BaseController
/** /**
* 新增设备基本信息 * 新增设备基本信息
* @ModelAttribute equBase
* @RequestPart(value = "file", required = false) // 使用 @RequestPart
* @ApiParam(value = "设备图片文件", type = "file")
* MultipartFile file
*/ */
@PreAuthorize("@ss.hasPermi('device:files:add')") @PreAuthorize("@ss.hasPermi('device:files:add')")
@Log(title = "设备基本信息", businessType = BusinessType.INSERT) @Log(title = "设备基本信息", businessType = BusinessType.INSERT)
@PostMapping(value = "/add") @PostMapping(value = "/add")
@ApiOperation("增加设备档案信息") @ApiOperation("增加设备档案信息")
public AjaxResult add( public AjaxResult add( @RequestBody EquBase equBase
@ModelAttribute EquBase equBase, ) {
@RequestPart(value = "file", required = false) // 使用 @RequestPart
@ApiParam(value = "设备图片文件", type = "file")
MultipartFile file
) throws IOException {
// 处理图片 // // 处理图片
if (file != null && !file.isEmpty()) { // if (file != null && !file.isEmpty()) {
equBase.setEquImage(file.getBytes()); // equBase.setEquImage(file.getBytes());
} // }
// 调用 Service 插入数据库 // 调用 Service 插入数据库
return toAjax(equBaseService.insertEquBase(equBase)); return toAjax(equBaseService.insertEquBase(equBase));
} }
/** /**
* @ModelAttribute EquBase equBase, // 自动绑定表单字段
* @RequestPart(value = "file", required = false) // 使用 @RequestPart
* @ApiParam(value = "设备图片文件", type = "file")
* MultipartFile file
* 修改设备基本信息 * 修改设备基本信息
*/ */
@PreAuthorize("@ss.hasPermi('device:files:edit')") @PreAuthorize("@ss.hasPermi('device:files:edit')")
@Log(title = "设备基本信息", businessType = BusinessType.UPDATE) @Log(title = "设备基本信息", businessType = BusinessType.UPDATE)
@PutMapping("/modify") @PutMapping("/modify")
@ApiOperation("修改设备档案信息") @ApiOperation("修改设备档案信息")
public AjaxResult edit( public AjaxResult edit(@RequestBody EquBase equBase){
@ModelAttribute EquBase equBase, // 自动绑定表单字段
@RequestPart(value = "file", required = false) // 使用 @RequestPart // // 处理图片
@ApiParam(value = "设备图片文件", type = "file") // if (file != null && !file.isEmpty()) {
MultipartFile file // equBase.setEquImage(file.getBytes()); // 存数据库 Blob
) throws IOException { // }
// 处理图片
if (file != null && !file.isEmpty()) {
equBase.setEquImage(file.getBytes()); // 存数据库 Blob
}
// 调用 Service 插入数据库 // 调用 Service 插入数据库
return toAjax(equBaseService.updateEquBase(equBase)); return toAjax(equBaseService.updateEquBase(equBase));

@ -33,7 +33,7 @@ import org.springframework.web.bind.annotation.RestController;
* @date 2025-08-01 * @date 2025-08-01
*/ */
@RestController @RestController
@RequestMapping("/deviceManu") @RequestMapping("/device/deviceManu")
public class EquManuController extends BaseController public class EquManuController extends BaseController
{ {
@Autowired @Autowired
@ -42,8 +42,8 @@ public class EquManuController extends BaseController
/** /**
* 查询设备厂商管理列表 * 查询设备厂商管理列表
*/ */
@PreAuthorize("@ss.hasPermi('device:deviceManu:queryByVO')") @PreAuthorize("@ss.hasPermi('device:deviceManu:query')")
@GetMapping("/queryByVO") @GetMapping("/query")
@ApiOperation("查询设备厂商管理列表") @ApiOperation("查询设备厂商管理列表")
public TableDataInfo list(EquManu equManu) public TableDataInfo list(EquManu equManu)
{ {

@ -1,8 +1,11 @@
package com.alops.web.controller.equManagement; package com.alops.web.controller.equManagement;
import java.util.List; import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.alops.system.domain.dto.EquSupplierAddDto;
import com.alops.system.domain.dto.EquSupplierUpdateDto;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import com.alops.common.annotation.Log; import com.alops.common.annotation.Log;
import com.alops.common.core.controller.BaseController; import com.alops.common.core.controller.BaseController;
@ -85,25 +88,27 @@ public class EquSupplierController extends BaseController
*/ */
@PreAuthorize("@ss.hasPermi('device:supplier:add')") @PreAuthorize("@ss.hasPermi('device:supplier:add')")
@Log(title = "供应商功能信息", businessType = BusinessType.INSERT) @Log(title = "供应商功能信息", businessType = BusinessType.INSERT)
@PostMapping @PostMapping("/add")
@ApiOperation("新增供应商功能信息列表") @ApiOperation("新增供应商功能信息")
public AjaxResult add(@RequestBody EquSupplier equSupplier) public AjaxResult add(@RequestBody EquSupplierAddDto dto)
{ {
return toAjax(equSupplierService.insertEquSupplier(equSupplier)); return toAjax(equSupplierService.insertEquSupplier(dto));
} }
/** /**
* 修改供应商功能信息 * 修改供应商功能信息
*/ */
@PreAuthorize("@ss.hasPermi('device:supplier:edit')") @PreAuthorize("@ss.hasPermi('device:supplier:edit')")
@Log(title = "供应商功能信息", businessType = BusinessType.UPDATE) @Log(title = "供应商功能信息", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping("/edit")
@ApiOperation("修改供应商功能信息列表") @ApiOperation("修改供应商功能信息列表")
public AjaxResult edit(@RequestBody EquSupplier equSupplier) public AjaxResult edit(@RequestBody EquSupplierUpdateDto updateDto) {
{ return toAjax(equSupplierService.updateEquSupplier(updateDto));
return toAjax(equSupplierService.updateEquSupplier(equSupplier));
} }
/** /**
* 删除供应商功能信息 * 删除供应商功能信息
*/ */

@ -58,25 +58,29 @@ public class ScheduleRulesController extends BaseController
@PreAuthorize("@ss.hasPermi('device:deviceInformation:protoCollect')") @PreAuthorize("@ss.hasPermi('device:deviceInformation:protoCollect')")
@PostMapping("/addRule") @PostMapping("/addRule")
@ApiOperation("立即确定") @ApiOperation("立即确定")
public AjaxResult run(@RequestBody ScheduleRules newRule) throws SchedulerException, ExecutionException, InterruptedException {
if (newRule.getRuleType() == 2) { public AjaxResult run(@RequestBody ScheduleRules newRule) throws SchedulerException, ExecutionException, InterruptedException {
// 立即执行
return scheduleRulesService.executeRule(newRule);
} else { // 先检查是否有任务正在执行
// 固定时间/按频率:异步处理异常 if (scheduleRulesService.checkRunningOrWaitingRules()) {
scheduleRulesService.executeRule(newRule); return AjaxResult.error(4001,"正在采集,请稍后,此次采集完成后会站内信通知到你");
}
return AjaxResult.success("任务已调度成功,异常会通过站内信/邮件通知"); // 执行规则(立即或定时/按频率)
} boolean success = scheduleRulesService.executeRule(newRule);
if (success) {
// 返回调度/插入成功
return AjaxResult.success("任务已调度成功,采集结果会通过站内信/邮件通知");
} else {
return AjaxResult.error("任务设置失败,请稍后重试");
}
} }
/** /**
* 查询定时采集规则列表 * 查询定时采集规则列表
*/ */

@ -1,34 +1,22 @@
package com.alops.web.controller.exceptionController; package com.alops.web.controller.exceptionController;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.alops.common.annotation.Log; import com.alops.common.annotation.Log;
import com.alops.common.core.controller.BaseController; import com.alops.common.core.controller.BaseController;
import com.alops.common.core.domain.AjaxResult; import com.alops.common.core.domain.AjaxResult;
import com.alops.common.core.page.TableDataInfo; import com.alops.common.core.page.TableDataInfo;
import com.alops.common.enums.BusinessType; import com.alops.common.enums.BusinessType;
import com.alops.common.utils.SecurityUtils;
import com.alops.common.utils.poi.ExcelUtil;
import com.alops.system.domain.AlertMessage; import com.alops.system.domain.AlertMessage;
import com.alops.system.domain.dto.AlertDto; import com.alops.system.domain.dto.AlertDto;
import com.alops.system.domain.vo.homeEquAlertMessageVo;
import com.alops.system.service.IAlertLaunchService; import com.alops.system.service.IAlertLaunchService;
import com.alops.system.domain.AlertRule;
import com.alops.system.domain.EquInterface;
import com.alops.system.domain.dto.AlertStatisticDto; import com.alops.system.domain.dto.AlertStatisticDto;
import com.alops.system.service.IAlertMessageService; import com.alops.system.service.IAlertMessageService;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** /**
* 故障统计Controller * 故障统计Controller
@ -91,12 +79,26 @@ public class AlertMessageController extends BaseController
/** /**
* 查询预警信息统计列表 * 查询预警信息统计列表
*/ */
@PreAuthorize("@ss.hasPermi('inMonitoring:alertMessage:list')") @PreAuthorize("@ss.hasPermi('inMonitoring:alertMessage:statistic:list')")
@PostMapping ("/list") @GetMapping ("/statistic/list")
@ApiOperation("查询预警信息") @ApiOperation("查询预警信息")
@Log(title = "查询预警信息", businessType = BusinessType.UPDATE) @Log(title = "查询预警信息", businessType = BusinessType.UPDATE)
public TableDataInfo homeList()
{
startPage();
List<homeEquAlertMessageVo> list = alertMessageService.selectStaticAlertMessageList();
return getDataTable(list);
}
public TableDataInfo list( @RequestBody AlertDto alertMessage) /**
* 首页查询预警信息统计列表
*/
@PreAuthorize("@ss.hasPermi('inMonitoring:alertMessage:list')")
@GetMapping ("/list")
@ApiOperation("查询预警信息")
@Log(title = "查询预警信息", businessType = BusinessType.UPDATE)
public TableDataInfo list( AlertDto alertMessage)
{ {
startPage(); startPage();
List<AlertMessage> list = alertMessageService.selectAlertMessageList(alertMessage); List<AlertMessage> list = alertMessageService.selectAlertMessageList(alertMessage);

@ -12,6 +12,7 @@ import com.alops.common.enums.BusinessType;
import com.alops.common.utils.poi.ExcelUtil; import com.alops.common.utils.poi.ExcelUtil;
import com.alops.system.domain.AlertRule; import com.alops.system.domain.AlertRule;
import com.alops.system.domain.dto.AlertRuleAddDto; import com.alops.system.domain.dto.AlertRuleAddDto;
import com.alops.system.domain.vo.AlertRuleVo;
import com.alops.system.service.IAlertLaunchService; import com.alops.system.service.IAlertLaunchService;
import com.alops.system.service.IAlertRuleService; import com.alops.system.service.IAlertRuleService;
import com.alops.system.service.IDictAlarmParamService; import com.alops.system.service.IDictAlarmParamService;
@ -55,7 +56,7 @@ public class AlertRuleController extends BaseController {
try { try {
AlertRule alertRule = alertRuleService.saveRule(dto); AlertRuleVo alertRule = alertRuleService.saveRule(dto);
return AjaxResult.success("预警规则新增成功", alertRule); return AjaxResult.success("预警规则新增成功", alertRule);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -69,7 +70,7 @@ public class AlertRuleController extends BaseController {
@PreAuthorize("@ss.hasPermi('inMonitoring:alertRule:edit')") @PreAuthorize("@ss.hasPermi('inMonitoring:alertRule:edit')")
@ApiOperation("修改预警规则") @ApiOperation("修改预警规则")
@Log(title = "【修改预警规则】", businessType = BusinessType.DELETE) @Log(title = "【修改预警规则】", businessType = BusinessType.DELETE)
@PostMapping("/editRule") @PutMapping("/editRule")
public AjaxResult editRule(@RequestBody AlertRuleAddDto dto) { public AjaxResult editRule(@RequestBody AlertRuleAddDto dto) {
try { try {
AlertRule alertRule = alertRuleService.updateRule(dto); AlertRule alertRule = alertRuleService.updateRule(dto);
@ -89,7 +90,7 @@ public class AlertRuleController extends BaseController {
@ApiOperation("查询预警规则") @ApiOperation("查询预警规则")
public TableDataInfo list(AlertRule alertRule) { public TableDataInfo list(AlertRule alertRule) {
startPage(); startPage();
List<AlertRule> list = alertRuleService.selectAlertRuleList(alertRule); List<AlertRuleVo> list = alertRuleService.selectAlertRuleList(alertRule);
return getDataTable(list); return getDataTable(list);
} }

@ -0,0 +1,41 @@
package com.alops.web.controller.exceptionController;
import com.alops.common.annotation.Log;
import com.alops.common.core.controller.BaseController;
import com.alops.common.core.page.TableDataInfo;
import com.alops.common.enums.BusinessType;
import com.alops.system.domain.vo.equipmentAssessmentVo;
import com.alops.system.service.IEquBaseService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/inMonitoring/equAssessment")
public class equAssessment extends BaseController {
@Autowired
public IEquBaseService iEquBaseService;
/**
* 设备信息评估表
* 获取所有设备id
*/
@PreAuthorize("@ss.hasPermi('inMonitoring:equAssessment:list')")
@GetMapping("/list")
@ApiOperation("设备评估信息")
@Log(title = "设备评估与预测", businessType = BusinessType.UPDATE)
public TableDataInfo homeList()
{
startPage();
List<equipmentAssessmentVo> list = iEquBaseService.getDeviceIAssessmentnfo();
return getDataTable(list);
}
}

@ -6,8 +6,8 @@ spring:
druid: druid:
# 主库数据源 # 主库数据源
master: master:
url: jdbc:mysql://localhost:3306/AIOps_sys?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 url: jdbc:mysql://localhost:3306/aiops_sys?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root username: aiops_sys
password: 1234 password: 1234
# 从库数据源 # 从库数据源
slave: slave:

@ -0,0 +1,14 @@
package com.alops.chat.repository;
import com.alops.chat.entity.UploadedFile;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* 上传文件信息Repository接口
* 提供对UploadedFile实体的基本CRUD操作
*/
@Repository
public interface UploadedFileRepository extends JpaRepository<UploadedFile, Long> {
// JpaRepository已经提供了基本的CRUD操作,可以根据需要添加自定义查询方法
}

@ -29,6 +29,8 @@ import com.alops.framework.security.context.AuthenticationContextHolder;
import com.alops.system.service.ISysConfigService; import com.alops.system.service.ISysConfigService;
import com.alops.system.service.ISysUserService; import com.alops.system.service.ISysUserService;
import java.util.Date;
/** /**
* 登录校验方法 * 登录校验方法
* *

@ -19,6 +19,8 @@ import com.alops.framework.manager.factory.AsyncFactory;
import com.alops.system.service.ISysConfigService; import com.alops.system.service.ISysConfigService;
import com.alops.system.service.ISysUserService; import com.alops.system.service.ISysUserService;
import java.util.Date;
/** /**
* 注册校验方法 * 注册校验方法
* *

@ -16,6 +16,18 @@
<description> <description>
system系统模块 system系统模块
</description> </description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>14</source>
<target>14</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies> <dependencies>
<!-- org.snmp4j --> <!-- org.snmp4j -->

@ -9,6 +9,8 @@ import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import javax.mail.Message;
/** /**
* 故障统计对象 alert_message * 故障统计对象 alert_message
* *
@ -23,7 +25,6 @@ public class AlertMessage
/** ID */ /** ID */
private Long id; private Long id;
/** 设备ID */ /** 设备ID */
@Excel(name = "设备ID") @Excel(name = "设备ID")
private String equId; private String equId;
@ -70,6 +71,9 @@ public class AlertMessage
@Excel(name = "信息批次") @Excel(name = "信息批次")
private Integer batch; private Integer batch;
@Excel(name ="预警信息")
private String message;

@ -62,6 +62,7 @@ public class AlertRule extends BaseEntity
public void setId(Long id) public void setId(Long id)
{ {
this.id = id; this.id = id;

@ -15,7 +15,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
* 设备基本信息对象 equ_base * 设备基本信息对象 equ_base
* *
* @author ruoyi * @author ruoyi
* @date 2025-09-19 * @date 2025-09-19F
*/ */
@Data @Data
public class EquBase public class EquBase
@ -25,6 +25,9 @@ public class EquBase
/** 设备唯一标识(设备编号) */ /** 设备唯一标识(设备编号) */
private String id; private String id;
/** (设备编号) */
private String equNumber;
/** 设备名称 */ /** 设备名称 */
@Excel(name = "设备名称") @Excel(name = "设备名称")
private String name; private String name;
@ -39,15 +42,8 @@ public class EquBase
/** 设备厂商 id */ /** 设备厂商 id */
@Excel(name = "设备厂商 id") @Excel(name = "设备厂商 id")
private String manufacture; private String equManuId;
public EquManu getManufactureVO() {
return manufactureVO;
}
public void setManufactureVO(EquManu manufactureVO) {
this.manufactureVO = manufactureVO;
}
private EquManu manufactureVO; private EquManu manufactureVO;
@ -57,7 +53,9 @@ public class EquBase
/** 设备类型 id */ /** 设备类型 id */
@Excel(name = "设备类型 id") @Excel(name = "设备类型 id")
private String equType; private String equTypeId;
public EquType getEquTypeVO() { public EquType getEquTypeVO() {
return equTypeVO; return equTypeVO;
@ -118,8 +116,8 @@ public class EquBase
@Excel(name = "采集次数") @Excel(name = "采集次数")
private Long createBy ; private Long createBy ;
@Excel(name = "设备图片") @Excel(name = "设备图片地址")
private byte[] equImage ; private String equImage ;
public void setId(String id) public void setId(String id)
@ -162,16 +160,6 @@ public class EquBase
return ip; return ip;
} }
public void setManufacture(String manufacture)
{
this.manufacture = manufacture;
}
public String getManufacture()
{
return manufacture;
}
public void setLocation(String location) public void setLocation(String location)
{ {
this.location = location; this.location = location;
@ -182,16 +170,6 @@ public class EquBase
return location; return location;
} }
public void setEquType(String equType)
{
this.equType = equType;
}
public String getEquType()
{
return equType;
}
public void setInCharge(String inCharge) public void setInCharge(String inCharge)
{ {
this.inCharge = inCharge; this.inCharge = inCharge;
@ -292,6 +270,11 @@ public class EquBase
return gatherFrequency; return gatherFrequency;
} }
public String getEquManuId() { return equManuId; }
public void setEquManuId(String equManuId) { this.equManuId = equManuId; }
public String getEquTypeId() { return equTypeId; }
public void setEquTypeId(String equTypeId) { this.equTypeId = equTypeId; }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -299,9 +282,9 @@ public class EquBase
.append("name", getName()) .append("name", getName())
.append("version", getVersion()) .append("version", getVersion())
.append("ip", getIp()) .append("ip", getIp())
.append("manufacture", getManufacture()) .append("equManuId", getEquManuId())
.append("location", getLocation()) .append("location", getLocation())
.append("equType", getEquType()) .append("equTypeId", getEquTypeId())
.append("inCharge", getInCharge()) .append("inCharge", getInCharge())
.append("installDate", getInstallDate()) .append("installDate", getInstallDate())
.append("lifeCycle", getLifeCycle()) .append("lifeCycle", getLifeCycle())

@ -17,7 +17,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
* @date 2025-08-20 * @date 2025-08-20
*/ */
@Data @Data
public class EquInterface extends BaseEntity public class EquInterface
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

@ -31,8 +31,8 @@ public class EquManu
@Excel(name = "厂商简介") @Excel(name = "厂商简介")
private String description; private String description;
/** 联系人ID */ /** 联系人*/
@Excel(name = "联系人ID") @Excel(name = "联系人")
private String contactBy; private String contactBy;
/** 联系方式 */ /** 联系方式 */

@ -14,7 +14,7 @@ import org.apache.ibatis.annotations.Mapper;
* @date 2025-08-15 * @date 2025-08-15
*/ */
@Data @Data
public class EquRouting extends BaseEntity public class EquRouting
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

@ -41,8 +41,8 @@ public class EquSupplier
@Excel(name = "l联系方式") @Excel(name = "l联系方式")
private String contactWay; private String contactWay;
/** 联系人姓名 */ /** 联系人姓名 */
@Excel(name = "创建人id") @Excel(name = "创建人")
private long createBy; private String createBy;
@ -117,12 +117,12 @@ public class EquSupplier
return status; return status;
} }
public Long getCreateBy() public String getCreateBy()
{ {
return createBy; return createBy;
} }
public void setCreateBy(Long createBy) public void setCreateBy(String createBy)
{ {
this.createBy = createBy; this.createBy = createBy;
} }

@ -14,7 +14,7 @@ import org.apache.ibatis.annotations.Mapper;
* @date 2025-08-15 * @date 2025-08-15
*/ */
@Data @Data
public class EquVeneer extends BaseEntity public class EquVeneer
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -34,8 +34,7 @@ public class EquVeneer extends BaseEntity
@Excel(name = "采集id") @Excel(name = "采集id")
private String equGatherId; private String equGatherId;
@Excel(name = "采集+预警同一批标志")
private String batchId;
public void setId(String id) public void setId(String id)
{ {

@ -1,6 +1,9 @@
package com.alops.system.domain.dto; package com.alops.system.domain.dto;
import lombok.Data; import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -8,15 +11,23 @@ import java.util.Map;
*/ */
@Data @Data
public class AlertStatisticDto { public class AlertStatisticDto {
// 按设备类型统计
private Map<String, Integer> typeCount;
// 按等级统计
private Map<Integer, Integer> levelCount;
// 本年度预警次数 private List<TypeCountDto> typeCount = new ArrayList<>();
private List<LevelCountDto> levelCount = new ArrayList<>();
private Integer yearCount; private Integer yearCount;
// 本月预警次数
private Integer monthCount; private Integer monthCount;
public List<TypeCountDto> getTypeCount() { return typeCount; }
public void setTypeCount(List<TypeCountDto> typeCount) { this.typeCount = typeCount; }
public List<LevelCountDto> getLevelCount() { return levelCount; }
public void setLevelCount(List<LevelCountDto> levelCount) { this.levelCount = levelCount; }
public Integer getYearCount() { return yearCount; }
public void setYearCount(Integer yearCount) { this.yearCount = yearCount; }
public Integer getMonthCount() { return monthCount; }
public void setMonthCount(Integer monthCount) { this.monthCount = monthCount; }
} }

@ -0,0 +1,112 @@
package com.alops.system.domain.dto;
import com.alops.common.annotation.Excel;
import com.alops.system.domain.EquManu;
import com.alops.system.domain.EquType;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class EquBaseAddDto {
private static final long serialVersionUID = 1L;
/** 设备唯一标识(设备编号) */
private String id;
/** (设备编号) */
private String equNumber;
/** 设备名称 */
@Excel(name = "设备名称")
private String name;
/** 设备版本 */
@Excel(name = "设备版本")
private String version;
/** 带外管理 IP */
@Excel(name = "带外管理 IP")
private String ip;
/** 设备厂商 id */
@Excel(name = "设备厂商 id")
private String manufacture;
private EquManu manufactureVO;
/** 安装位置 */
@Excel(name = "安装位置 ")
private String location;
/** 设备类型 id */
@Excel(name = "设备类型 id")
private String equType;
public EquType getEquTypeVO() {
return equTypeVO;
}
public void setEquTypeVO(EquType equTypeVO) {
this.equTypeVO = equTypeVO;
}
private EquType equTypeVO;
/** 设备管理员姓名 */
@Excel(name = "设备管理员姓名")
private String inCharge;
/** 安装日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "安装日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date installDate;
/** 预计年限(年) */
@Excel(name = "预计年限(年)")
private Long lifeCycle;
/** 质保时间(年) */
@Excel(name = "质保时间(年)")
private Long warranty;
/** 添加日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "添加日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date createDate;
/** 启用状态(1启用0禁用) */
@Excel(name = "启用状态", readConverterExp = "0=启用1禁用")
private Long status;
/** 累计预警次数 */
@Excel(name = "累计预警次数")
private Long failureFrequency;
/** 设备级别 */
@Excel(name = "设备级别")
private String deviceLevel;
/** 供应商id */
@Excel(name = "供应商id")
private String supplierId;
/** 采集次数 */
@Excel(name = "采集次数")
private Long gatherFrequency;
@Excel(name = "采集次数")
private Long createBy ;
@Excel(name = "设备图片地址")
private String equImage ;
}

@ -16,18 +16,17 @@ public class EquBaseQueryDto implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private String id; private String id;
/** 设备类型 (equ_type, varchar) */
private String equTypeId;
/** 设备类型 (equ_type, varchar) */
private String equTypeId;
/** 设备类型 (equ_type, varchar) */ /** 设备类型 (equ_type, varchar) */
private String equType; private String equType;
/** 设备名称 (name, varchar) */ /** 设备名称 (name, varchar) */
private String name; private String name;
/** 安装位置 ID (location, varchar) */ /** 安装位置 ID (location, varchar) */
private String location; private String location;
/** 起始时间 (min_time) */ /** 起始时间 (min_time) */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date minTime; private Date minTime;
@ -40,8 +39,6 @@ public class EquBaseQueryDto implements Serializable {
private Integer status; private Integer status;
// ====== Getter 和 Setter ====== // ====== Getter 和 Setter ======
public String getName() { public String getName() {
return name; return name;
} }

@ -0,0 +1,22 @@
package com.alops.system.domain.dto;
import lombok.Data;
import java.util.Date;
/**
* 首页展示设备监测简要信息
*/
@Data
public class EquMonitorHomeDto {
private String id;
private String equNumber; //设备编号
private String name; // 设备名称
private String location; // 设备位置
private Float cpuUtilization; // CPU 使用率
private Float memoryUtilization; // 内存使用率
private Float temperature; // 温度
private String health; // 健康度
private String contWorkPeriod; // 持续运行时长
private Date gatherTime; // 采集时间
}

@ -0,0 +1,17 @@
package com.alops.system.domain.dto;
import lombok.Data;
/**
* 新增供应商 DTO
* 只包含前端可传的字段
*/
@Data
public class EquSupplierAddDto {
private String name;
private String description;
private String contactBy;
private String contactWay;
private Long status;
}

@ -0,0 +1,13 @@
package com.alops.system.domain.dto;
import lombok.Data;
@Data
public class EquSupplierUpdateDto {
private String contactBy;
private String contactWay;
private String description;
private String id;
private String name;
private Long status;
}

@ -0,0 +1,22 @@
package com.alops.system.domain.dto;
public class LevelCountDto {
private String level;
private Integer count;
// 无参构造器
public LevelCountDto() {}
// 带参构造器
public LevelCountDto(String level, Integer count) {
this.level = level;
this.count = count;
}
// getter & setter
public String getLevel() { return level; }
public void setLevel(String level) { this.level = level; }
public Integer getCount() { return count; }
public void setCount(Integer count) { this.count = count; }
}

@ -7,9 +7,9 @@ import java.util.List;
public class MonitorHistoryDto { public class MonitorHistoryDto {
// 返回给前端的字段 // 返回给前端的字段
private List<Float> temperatureList = new ArrayList<>(); private List<Float> temperatureList = new ArrayList<>();
private List<Float> involtageList = new ArrayList<>(); private List<Float> memoryList = new ArrayList<>();
private List<Float> outvoltageList = new ArrayList<>(); private List<Float> cpuList = new ArrayList<>();
private List<Float> healthList = new ArrayList<>();
private List<String> timeList = new ArrayList<>(); private List<String> timeList = new ArrayList<>();
} }

@ -1,19 +1,25 @@
package com.alops.system.domain.dto; package com.alops.system.domain.dto;
import lombok.Data; import lombok.Data;
import java.sql.Blob;
import java.util.Date; import java.util.Date;
@Data @Data
public class MonitorLastDto { public class MonitorLastDto {
// equ_gather 表 // equ_gather 表
private Integer contWorkPeriod; private String contWorkPeriod;
private Float fanSpeed; private Float fanSpeed;
private Float cpuUtilization; private Float cpuUtilization;
private Float memoryUtilization; private Float memoryUtilization;
private String health; private String health;
private String volIn;
private String volOut;
private String temperature;
// equ_base 表 // equ_base 表
private Long id; private String id;
private String equNumber;
private String name; private String name;
private String version; private String version;
private String deviceLevel; private String deviceLevel;
@ -21,17 +27,24 @@ public class MonitorLastDto {
private String location; private String location;
private Date installDate; private Date installDate;
private String inCharge; private String inCharge;
private Integer failureFrequency; private String status;
private Integer warranty;
private int warranty;
private String equImage;
// equ_type // equ_type
private String equType; private String equTypeId;
private String equTypeName;
// equ_manu // equ_manu
private String manufacture; private String equManuId;
private String manufactureContactBy; private String equManuName;
private String manufactureContactWay; private String ContactBy;
private String ContactWay;
// equ_supplier // equ_supplier
private String supplierId; private String supplierId;
private String supplierName;
private int AlertCount;
private String unhandledAlertCount;
} }

@ -11,15 +11,23 @@ import java.sql.Blob;
public class MonitorListDto { public class MonitorListDto {
private String id; private String id;
private String name; private String name;
private String ip;
private String equTypeId;
private String equTypeName;
private String equManuId;
private String equManuName;
private String version; private String version;
private String deviceLevel; private String deviceLevel;
private String location; private String location;
private String status; private String status;
private Integer failureFrequency;
private Blob equImage;
// 监控指标 // 监控指标
private Float cpuUtilization; private Float cpuUtilization;
private String health; private String health;
private Integer fanSpeed; private int fanSpeed;
private String contWorkPeriod;
private int AlertCount;;
private int unhandledAlertCount;
} }

@ -11,6 +11,11 @@ public class MonitorStatisticDto {
private String equTypeName; // 设备类型名称 private String equTypeName; // 设备类型名称
private List<DeviceSimpleInfo> devices; // 属于该类型的设备列表 private List<DeviceSimpleInfo> devices; // 属于该类型的设备列表
// 新增统计数量字段
private Integer count;
// 每类型占总设备数量的百分比
private Double percentage;
@Data @Data
public static class DeviceSimpleInfo { public static class DeviceSimpleInfo {
private String id; private String id;

@ -0,0 +1,17 @@
package com.alops.system.domain.dto;
public class TypeCountDto {
private String name;
private Integer count;
public TypeCountDto() {}
public TypeCountDto(String name, Integer count) {
this.name = name;
this.count = count;
}
// getter/setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getCount() { return count; }
public void setCount(Integer count) { this.count = count; }
}

@ -0,0 +1,48 @@
package com.alops.system.domain.dto;
import com.alops.common.annotation.Excel;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class equipmentAssessmentDto {
/** 设备唯一标识(设备编号) */
private String id;
/** (设备编号) */
private String equNumber;
/** 设备名称 */
@Excel(name = "设备名称")
private String name;
/** 安装位置 */
@Excel(name = "安装位置 ")
private String location;
/** 设备类型 id */
@Excel(name = "设备类型名称")
private String equType;
/** 设备级别 */
@Excel(name = "设备级别")
private String deviceLevel;
@Excel(name = "综合计算的健康度指标(%)")
private BigDecimal health;
/** 设备温度 */
@Excel(name = "设备温度")
private BigDecimal temperature;
/** CPU 使用率(%) */
@Excel(name = "CPU 使用率(%)")
private BigDecimal cpuUtilization;
/** 内存使用率(%) */
@Excel(name = "内存使用率(%)")
private BigDecimal memoryUtilization;
}

@ -0,0 +1,75 @@
package com.alops.system.domain.vo;
import com.alops.common.annotation.Excel;
import com.alops.common.core.domain.BaseEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.util.Date;
@Data
public class AlertRuleVo extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
/** 预警规则名称 */
@Excel(name = "预警规则名称")
private String ruleName;
/** 预警级别 */
@Excel(name = "预警级别")
private Long severity;
/** 预警方式(email/message) */
@Excel(name = "预警方式(email/message)")
private String alertWay;
/** 预警到站方 */
@Excel(name = "预警到站方")
private String alertStation;
/** 预警规则内容描述 */
@Excel(name = "预警规则内容描述")
private String description;
/** 启用状态(0为启用) */
@Excel(name = "启用状态", readConverterExp = "0=为启用")
private Integer enable;
/** 表格名称 */
@Excel(name = "表格名称")
private String tableName;
/** 预警sql语句查询 */
@Excel(name = "预警sql语句查询")
@JsonIgnore
private String alertSql;
/** 预警模版(参数用数据库命名法) */
@Excel(name = "预警模版", readConverterExp = "参=数用数据库命名法")
private String alertTemplate;
/** 预警类型 */
@Excel(name = "预警类型")
private String type;
/** 参数名称 */
@Excel(name = "参数名称")
private String paramName;
/** 比较符号 */
@Excel(name = "比较符号")
private String operator;
/** 比较值 */
@Excel(name = "比较值")
private String compareValue;
}

@ -0,0 +1,45 @@
package com.alops.system.domain.vo;
import com.alops.common.annotation.Excel;
import lombok.Data;
@Data
public class equipmentAssessmentVo {
/** 设备唯一标识(设备编号) */
private String id;
/** (设备编号) */
private String equNumber;
/** 设备名称 */
@Excel(name = "设备名称")
private String name;
/** 安装位置 */
@Excel(name = "安装位置 ")
private String location;
/** 设备类型 id */
@Excel(name = "设备类型名称")
private String equType;
/** 设备级别 */
@Excel(name = "设备级别")
private String deviceLevel;
/** CPU使用率(%) */
private String cpuStatus;
/** 内存使用率(%) */
private String memoryStatus;
/** 温度(℃) */
private String temperatureStatus;
/** 健康状态(健康、良好、一般、需维护) */
private String healthStatus;
/** 风险等级 */
private String riskGrade ;
}

@ -0,0 +1,37 @@
package com.alops.system.domain.vo;
import com.alops.common.annotation.Excel;
import lombok.Data;
import java.util.Date;
@Data
public class homeEquAlertMessageVo {
/** 预警级别(1-5级) */
@Excel(name = "预警级别(1-5级)")
private Long level;
/** 发生时间 */
@Excel(name = "发生时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date occurTime;
@Excel(name = "预警信息")
private String message;
/** 处理状态(open、in_progress_closed) */
@Excel(name = "处理状态")
private String status;
@Excel(name = "处理状态")
private String name;
@Excel(name = "处理状态")
private String location;
}

@ -39,17 +39,23 @@ public class queryEquBaseVO {
/** 带外管理 IP */ /** 带外管理 IP */
@Excel(name = "带外管理 IP") @Excel(name = "带外管理 IP")
private String ip; private String ip;
@Excel(name = "设备厂商名称id ")
private String equManuId;
/** 设备厂商 */ /** 设备厂商 */
@Excel(name = "设备厂商名称 ") @Excel(name = "设备厂商名称 ")
private String manuName; private String manufacture;
/** 设备厂商 */ /** 设备厂商 */
@Excel(name = "设备厂商名称 ") @Excel(name = "设备供应商名称 ")
private String supplierId;
/** 安装位置 id */
@Excel(name = "设备供应商名称 ")
private String supplierName; private String supplierName;
/** 安装位置 id */ /** 安装位置 id */
@Excel(name = "安装位置 id") @Excel(name = "安装位置 id")
private String location; private String location;
/** 设备类型 id */
/** 设备类型 id */ @Excel(name = "设备类型id")
private String equTypeId;
@Excel(name = "设备类型名称") @Excel(name = "设备类型名称")
private String equType; private String equType;
@ -59,7 +65,7 @@ public class queryEquBaseVO {
/** 安装日期 */ /** 安装日期 */
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "安装日期", width = 30, dateFormat = "yyyy-MM-dd") @Excel(name = "安装日期", width = 30)
private Date installDate; private Date installDate;
/** 预计年限(年) */ /** 预计年限(年) */
@ -78,8 +84,8 @@ public class queryEquBaseVO {
@Excel(name = "健康度") @Excel(name = "健康度")
private BigDecimal health; private BigDecimal health;
/** 添加日期 */ /** 添加日期 */
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "添加日期", width = 30, dateFormat = "yyyy-MM-dd") @Excel(name = "添加日期", width = 30)
private Date createDate; private Date createDate;
/** 启用状态 */ /** 启用状态 */
@Excel(name = "启用状态") @Excel(name = "启用状态")
@ -88,6 +94,12 @@ public class queryEquBaseVO {
@Excel(name = "累积故障次数") @Excel(name = "累积故障次数")
private String deviceLevel; private String deviceLevel;
@Excel(name = "设备图片")
private String equImage;
@Excel(name = "设备编号")
private String equNumber;
public void setId(String id) public void setId(String id)
{ {
@ -226,7 +238,7 @@ public class queryEquBaseVO {
.append("version", getVersion()) .append("version", getVersion())
.append("ip", getIp()) .append("ip", getIp())
.append("supplierName", getSupplierName()) .append("supplierName", getSupplierName())
.append("manuName", getManuName()) .append("manuName", getManufacture())
.append("location", getLocation()) .append("location", getLocation())
.append("equType", getEquType()) .append("equType", getEquType())
.append("inCharge", getInCharge()) .append("inCharge", getInCharge())

@ -39,7 +39,23 @@ public class GatherJob implements Job {
try { try {
if (rule == null) return; if (rule == null) return;
// 按频率判断时间范围 // 1.状态为4时取消调度任务
if (rule.getStatus() == 4) {
Scheduler scheduler = context.getScheduler();
JobKey jobKey = context.getJobDetail().getKey();
scheduler.deleteJob(jobKey);
String Content=String.format("任务执行完此次,已取消后续任务");
iAlertSenderService.sendInternalMessage( Content,"2" );
log.info("规则[{}] 已标记为取消状态(4),对应定时任务已删除: {}", rule.getId(), jobKey);
return;
}
// 2.设置状态为执行中
rule.setStatus(1);
scheduleRulesMapper.updateScheduleRules(rule);
// 3.判断是否执行完成 按频率判断时间范围
if (rule.getRuleType() == 0) { if (rule.getRuleType() == 0) {
Date start = rule.getStartTime(); Date start = rule.getStartTime();
Date end = rule.getEndTime(); Date end = rule.getEndTime();
@ -48,7 +64,6 @@ public class GatherJob implements Job {
if ( now.after(end)) { if ( now.after(end)) {
rule.setStatus(2); // 超出范围标记完成 rule.setStatus(2); // 超出范围标记完成
scheduleRulesMapper.updateScheduleRules(rule); scheduleRulesMapper.updateScheduleRules(rule);
return; return;
} }
} }
@ -58,10 +73,17 @@ public class GatherJob implements Job {
iScheduleRulesService.executeImmediately(); iScheduleRulesService.executeImmediately();
// 执行成功 // 执行成功
if (rule.getRuleType() == 0 || rule.getRuleType() == 1) { if (rule.getRuleType() == 1 ) {
rule.setStatus(2); rule.setStatus(2);
String Content=String.format("任务执行完成",
rule.getId(), rule.getRuleName());
iAlertSenderService.sendInternalMessage( Content,"2" );
scheduleRulesMapper.updateScheduleRules(rule);
} }
scheduleRulesMapper.updateScheduleRules(rule);
} catch (Exception e) { } catch (Exception e) {
//执行失败是不会有采集信息和预警信息的 //执行失败是不会有采集信息和预警信息的

@ -2,6 +2,7 @@ package com.alops.system.mapper;
import com.alops.system.domain.AlertMessage; import com.alops.system.domain.AlertMessage;
import com.alops.system.domain.dto.AlertDto; import com.alops.system.domain.dto.AlertDto;
import com.alops.system.domain.vo.homeEquAlertMessageVo;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -44,6 +45,8 @@ public interface AlertMessageMapper
* @return 故障统计集合 * @return 故障统计集合
*/ */
public List<AlertMessage> selectAlertMessageList(AlertDto alertMessage); public List<AlertMessage> selectAlertMessageList(AlertDto alertMessage);
public List<homeEquAlertMessageVo> selectStaticAlertMessageList();
public ArrayList<AlertMessage> selectAlertMessageByEquId(Long Equid); public ArrayList<AlertMessage> selectAlertMessageByEquId(Long Equid);
/** /**

@ -2,6 +2,7 @@ package com.alops.system.mapper;
import com.alops.system.domain.AlertRule; import com.alops.system.domain.AlertRule;
import com.alops.system.domain.dto.AlertRuleAddDto; import com.alops.system.domain.dto.AlertRuleAddDto;
import com.alops.system.domain.vo.AlertRuleVo;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
@ -26,15 +27,15 @@ public interface AlertRuleMapper
* @param id 请填写功能名称主键 * @param id 请填写功能名称主键
* @return 请填写功能名称 * @return 请填写功能名称
*/ */
public AlertRule selectAlertRuleById(Long id); public AlertRuleVo selectAlertRuleById(Long id);
public AlertRule selectAlertRuleByToId(Long id);
/** /**
* 查询请填写功能名称列表 * 查询请填写功能名称列表
* *
* @param alertRule 请填写功能名称 * @param alertRule 请填写功能名称
* @return 请填写功能名称集合 * @return 请填写功能名称集合
*/ */
public List<AlertRule> selectAlertRuleList(AlertRule alertRule); public List<AlertRuleVo> selectAlertRuleList(AlertRule alertRule);
/** /**
* 新增请填写功能名称 * 新增请填写功能名称

@ -4,19 +4,13 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.alops.system.domain.EquBase; import com.alops.system.domain.EquBase;
import com.alops.system.domain.dto.EquBaseQueryDto; import com.alops.system.domain.dto.*;
import com.alops.system.domain.dto.MonitorLastDto;
import com.alops.system.domain.dto.MonitorListDto;
import com.alops.system.domain.dto.MonitorStatisticDto;
import com.alops.system.domain.vo.imageVo; import com.alops.system.domain.vo.imageVo;
import com.alops.system.domain.vo.queryEquBaseVO; import com.alops.system.domain.vo.queryEquBaseVO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update; import org.apache.ibatis.annotations.Update;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Map;
/** /**
* 设备基本信息Mapper接口 * 设备基本信息Mapper接口
@ -27,6 +21,12 @@ import java.util.Map;
@Mapper @Mapper
public interface EquBaseMapper public interface EquBaseMapper
{ {
/**
* 查询状态为1的设备及其最新采集信息和类型名称
*/
List<equipmentAssessmentDto> getEquipmentAssessmentList();
int incrementCollectCount(@Param("ids") List<String> ids); int incrementCollectCount(@Param("ids") List<String> ids);
@Update("DELETE FROM equ_interface") @Update("DELETE FROM equ_interface")
@ -63,7 +63,13 @@ public interface EquBaseMapper
MonitorLastDto selectEquMonitorById(String id); MonitorLastDto selectEquMonitorById(String id);
List<Map<String, Object>> selectEquMonitorByIdToList(EquBaseQueryDto queryDto); List<Map<String, Object>> selectEquMonitorByIdToList(EquBaseQueryDto queryDto);
List<MonitorListDto> selectEquMonitorList(EquBaseQueryDto equBaseQueryDto); List<MonitorListDto> selectEquMonitorListPaged();
/**
* 查询每台设备的最新监测信息首页展示用
*/
List<EquMonitorHomeDto> selectLatestEquMonitorList();
/**分类统计界面信息 -YY**/ /**分类统计界面信息 -YY**/
List<MonitorStatisticDto> selectEquStatisticByType(); List<MonitorStatisticDto> selectEquStatisticByType();

@ -17,6 +17,8 @@ public interface ScheduleRulesMapper
public List<ScheduleRules> selectList(); public List<ScheduleRules> selectList();
public List<ScheduleRules> selectListOne();
/** /**
* 查询定时采集规则 * 查询定时采集规则
* *

@ -3,6 +3,7 @@ package com.alops.system.service;
import com.alops.system.domain.AlertMessage; import com.alops.system.domain.AlertMessage;
import com.alops.system.domain.dto.AlertDto; import com.alops.system.domain.dto.AlertDto;
import com.alops.system.domain.dto.AlertStatisticDto; import com.alops.system.domain.dto.AlertStatisticDto;
import com.alops.system.domain.vo.homeEquAlertMessageVo;
import java.util.List; import java.util.List;
@ -30,7 +31,7 @@ public interface IAlertMessageService
* @return 故障统计集合 * @return 故障统计集合
*/ */
public List<AlertMessage> selectAlertMessageList(AlertDto alertMessage); public List<AlertMessage> selectAlertMessageList(AlertDto alertMessage);
public List<homeEquAlertMessageVo> selectStaticAlertMessageList();
public List<AlertMessage> selectAlertMessageListByEquId(Long equId); public List<AlertMessage> selectAlertMessageListByEquId(Long equId);
/** /**

@ -2,6 +2,7 @@ package com.alops.system.service;
import com.alops.system.domain.AlertRule; import com.alops.system.domain.AlertRule;
import com.alops.system.domain.dto.AlertRuleAddDto; import com.alops.system.domain.dto.AlertRuleAddDto;
import com.alops.system.domain.vo.AlertRuleVo;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -15,7 +16,7 @@ import java.util.Map;
public interface IAlertRuleService public interface IAlertRuleService
{ {
public AlertRule saveRule(AlertRuleAddDto dto); public AlertRuleVo saveRule(AlertRuleAddDto dto);
public AlertRule updateRule(AlertRuleAddDto dto); public AlertRule updateRule(AlertRuleAddDto dto);
@ -40,7 +41,7 @@ public interface IAlertRuleService
* @param alertRule 请填写功能名称 * @param alertRule 请填写功能名称
* @return 请填写功能名称集合 * @return 请填写功能名称集合
*/ */
public List<AlertRule> selectAlertRuleList(AlertRule alertRule); public List<AlertRuleVo> selectAlertRuleList(AlertRule alertRule);
/** /**
* 新增请填写功能名称 * 新增请填写功能名称

@ -3,6 +3,7 @@ package com.alops.system.service;
import com.alops.system.domain.EquBase; import com.alops.system.domain.EquBase;
import com.alops.system.domain.dto.EquBaseQueryDto; import com.alops.system.domain.dto.EquBaseQueryDto;
import com.alops.system.domain.vo.dropDownVo; import com.alops.system.domain.vo.dropDownVo;
import com.alops.system.domain.vo.equipmentAssessmentVo;
import com.alops.system.domain.vo.imageVo; import com.alops.system.domain.vo.imageVo;
import com.alops.system.domain.dto.*; import com.alops.system.domain.dto.*;
import com.alops.system.domain.vo.queryEquBaseVO; import com.alops.system.domain.vo.queryEquBaseVO;
@ -18,7 +19,8 @@ import java.util.List;
*/ */
public interface IEquBaseService public interface IEquBaseService
{ {
//获取设备评估信息
public List<equipmentAssessmentVo> getDeviceIAssessmentnfo();
public List<dropDownVo> selectEquManu(); public List<dropDownVo> selectEquManu();
public List<dropDownVo> selectEquSupp(); public List<dropDownVo> selectEquSupp();
@ -60,7 +62,12 @@ public interface IEquBaseService
*/ */
public List<queryEquBaseVO> selectEquBaseList(EquBaseQueryDto equBase); public List<queryEquBaseVO> selectEquBaseList(EquBaseQueryDto equBase);
public List<MonitorListDto> selectEquMonitorList(EquBaseQueryDto equBaseQueryDto); public List<MonitorListDto> selectEquMonitorListPaged();
/**
* 查询每台设备的最新监测信息首页展示用
*/
List<EquMonitorHomeDto> selectLatestEquMonitorList();
/**分类统计信息**/ /**分类统计信息**/
List<MonitorStatisticDto> selectEquStatisticByType(); List<MonitorStatisticDto> selectEquStatisticByType();

@ -2,6 +2,8 @@ package com.alops.system.service;
import java.util.List; import java.util.List;
import com.alops.system.domain.EquSupplier; import com.alops.system.domain.EquSupplier;
import com.alops.system.domain.dto.EquSupplierAddDto;
import com.alops.system.domain.dto.EquSupplierUpdateDto;
import java.util.List; import java.util.List;
@ -31,19 +33,17 @@ public interface IEquSupplierService
/** /**
* 新增请填写功能名称 * 新增请填写功能名称
*
* @param equSupplier 请填写功能名称
* @return 结果 * @return 结果
*/ */
public int insertEquSupplier(EquSupplier equSupplier); public int insertEquSupplier(EquSupplierAddDto dto);
/** /**
* 修改请填写功能名称 * 修改请填写功能名称
* *
* @param equSupplier 请填写功能名称
* @return 结果 * @return 结果
*/ */
public int updateEquSupplier(EquSupplier equSupplier); public int updateEquSupplier(EquSupplierUpdateDto updateDto);
/** /**
* 批量删除请填写功能名称 * 批量删除请填写功能名称

@ -21,7 +21,9 @@ public interface IScheduleRulesService
public AjaxResult executeRule(ScheduleRules newRule) throws SchedulerException, ExecutionException, InterruptedException; public Boolean checkRunningOrWaitingRules() throws SchedulerException;
public Boolean executeRule(ScheduleRules newRule) throws SchedulerException, ExecutionException, InterruptedException;
public int executeImmediately() throws ExecutionException, InterruptedException; public int executeImmediately() throws ExecutionException, InterruptedException;
/** /**

@ -153,7 +153,7 @@ public class AlertLaunchServiceImpl implements IAlertLaunchService {
String msgdes = fillTemplate(rule.getAlertTemplate(), row, rule); String msgdes = fillTemplate(rule.getAlertTemplate(), row, rule);
msg.setBatch(currentBatch); msg.setBatch(currentBatch);
msg.setMessage(msgdes);
messages.add(msg); messages.add(msg);
msgs.add(msgdes); msgs.add(msgdes);
@ -213,7 +213,7 @@ public class AlertLaunchServiceImpl implements IAlertLaunchService {
// 3. SQL:取每台设备最新记录和次新记录,比较该字段是否变化,并关联设备类型 // 3. SQL:取每台设备最新记录和次新记录,比较该字段是否变化,并关联设备类型
String sql = String sql =
"SELECT g1.*, t.name AS equ_type,b.name AS equ_name" + "SELECT g1.*, t.name AS equ_type,b.name AS equ_name,b.equ_number" +
"FROM equ_gather g1 " + "FROM equ_gather g1 " +
"JOIN equ_gather g2 ON g1.equ_id = g2.equ_id " + "JOIN equ_gather g2 ON g1.equ_id = g2.equ_id " +
"JOIN equ_base b ON g1.equ_id = b.id " + "JOIN equ_base b ON g1.equ_id = b.id " +

@ -2,7 +2,6 @@ package com.alops.system.service.impl;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -10,6 +9,9 @@ import java.util.Map;
import com.alops.system.domain.AlertMessage; import com.alops.system.domain.AlertMessage;
import com.alops.system.domain.dto.AlertDto; import com.alops.system.domain.dto.AlertDto;
import com.alops.system.domain.dto.AlertStatisticDto; import com.alops.system.domain.dto.AlertStatisticDto;
import com.alops.system.domain.dto.LevelCountDto;
import com.alops.system.domain.dto.TypeCountDto;
import com.alops.system.domain.vo.homeEquAlertMessageVo;
import com.alops.system.mapper.AlertMessageMapper; import com.alops.system.mapper.AlertMessageMapper;
import com.alops.system.service.IAlertMessageService; import com.alops.system.service.IAlertMessageService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -51,6 +53,12 @@ public class AlertMessageServiceImpl implements IAlertMessageService
return alertMessageMapper.selectAlertMessageList(alertMessage); return alertMessageMapper.selectAlertMessageList(alertMessage);
} }
@Override
public List<homeEquAlertMessageVo> selectStaticAlertMessageList(){
return alertMessageMapper.selectStaticAlertMessageList();
}
@Override @Override
public List<AlertMessage> selectAlertMessageListByEquId(Long equId) public List<AlertMessage> selectAlertMessageListByEquId(Long equId)
{ {
@ -66,18 +74,18 @@ public class AlertMessageServiceImpl implements IAlertMessageService
AlertStatisticDto dto = new AlertStatisticDto(); AlertStatisticDto dto = new AlertStatisticDto();
// 按设备类型统计 // 按设备类型统计
Map<String, Integer> typeMap = new HashMap<>();
for (Map<String, Object> row : alertMessageMapper.countByType()) { for (Map<String, Object> row : alertMessageMapper.countByType()) {
typeMap.put((String) row.get("equ_type"), ((Long) row.get("cnt")).intValue()); String name = (String) row.get("equ_type");
Integer count = ((Long) row.get("cnt")).intValue();
dto.getTypeCount().add(new TypeCountDto(name, count));
} }
dto.setTypeCount(typeMap);
// 按等级统计 // 按等级统计
Map<Integer, Integer> levelMap = new HashMap<>();
for (Map<String, Object> row : alertMessageMapper.countByLevel()) { for (Map<String, Object> row : alertMessageMapper.countByLevel()) {
levelMap.put(((Integer) row.get("level")), ((Long) row.get("cnt")).intValue()); String level = String.valueOf(row.get("level"));
Integer count = ((Long) row.get("cnt")).intValue();
dto.getLevelCount().add(new LevelCountDto(level, count));
} }
dto.setLevelCount(levelMap);
// 年 / 月 // 年 / 月
LocalDate now = LocalDate.now(); LocalDate now = LocalDate.now();
@ -90,7 +98,8 @@ public class AlertMessageServiceImpl implements IAlertMessageService
return dto; return dto;
} }
/**
/**
* 新增故障统计 * 新增故障统计
* *
* @param alertMessage 故障统计 * @param alertMessage 故障统计

@ -8,6 +8,7 @@ import com.alops.common.utils.SecurityUtils;
import com.alops.system.domain.AlertRule; import com.alops.system.domain.AlertRule;
import com.alops.system.domain.AlertRuleCondition; import com.alops.system.domain.AlertRuleCondition;
import com.alops.system.domain.dto.AlertRuleAddDto; import com.alops.system.domain.dto.AlertRuleAddDto;
import com.alops.system.domain.vo.AlertRuleVo;
import com.alops.system.mapper.AlertRuleConditionMapper; import com.alops.system.mapper.AlertRuleConditionMapper;
import com.alops.system.mapper.AlertRuleMapper; import com.alops.system.mapper.AlertRuleMapper;
import com.alops.system.service.IAlertRuleService; import com.alops.system.service.IAlertRuleService;
@ -37,7 +38,7 @@ public class AlertRuleServiceImpl implements IAlertRuleService
*/ */
@Override @Override
public AlertRule saveRule(AlertRuleAddDto dto) { public AlertRuleVo saveRule(AlertRuleAddDto dto) {
Long userId = SecurityUtils.getLoginUser().getUserId(); Long userId = SecurityUtils.getLoginUser().getUserId();
AlertRule rule = dto.getAlertRule(); AlertRule rule = dto.getAlertRule();
@ -56,7 +57,7 @@ public class AlertRuleServiceImpl implements IAlertRuleService
sql = buildSql(rule, conditions); sql = buildSql(rule, conditions);
} }
rule.setAlertSql(sql); rule.setAlertSql(sql);
rule.setEnable(1);
// 插入规则 // 插入规则
alertRuleMapper.insertAlertRule(rule); alertRuleMapper.insertAlertRule(rule);
@ -67,7 +68,7 @@ public class AlertRuleServiceImpl implements IAlertRuleService
alertRuleConditionMapper.insertAlertRuleCondition(c); alertRuleConditionMapper.insertAlertRuleCondition(c);
} }
} }
AlertRule fullRule = alertRuleMapper.selectAlertRuleById(rule.getId()); AlertRuleVo fullRule = alertRuleMapper.selectAlertRuleById(rule.getId());
return fullRule; return fullRule;
} }
@ -104,14 +105,14 @@ public class AlertRuleServiceImpl implements IAlertRuleService
alertRuleConditionMapper.insertAlertRuleCondition(c); alertRuleConditionMapper.insertAlertRuleCondition(c);
} }
} }
AlertRule fullRule = alertRuleMapper.selectAlertRuleById(rule.getId()); AlertRule fullRule = alertRuleMapper.selectAlertRuleByToId(rule.getId());
return fullRule; return fullRule;
} }
@Override @Override
public AlertRuleAddDto selectDetailAlertRuleById(Long id) { public AlertRuleAddDto selectDetailAlertRuleById(Long id) {
// 1. 查询主表 // 1. 查询主表
AlertRule rule = alertRuleMapper.selectAlertRuleById(id); AlertRule rule = alertRuleMapper.selectAlertRuleByToId(id);
if (rule == null) { if (rule == null) {
return null; return null;
} }
@ -140,7 +141,7 @@ public class AlertRuleServiceImpl implements IAlertRuleService
if ("equ_gather".equalsIgnoreCase(rule.getTableName())) { if ("equ_gather".equalsIgnoreCase(rule.getTableName())) {
// equ_gather 作为主表 // equ_gather 作为主表
sql.append("g.*, t.name AS equ_type ,b.name AS equ_name") sql.append("g.*, t.name AS equ_type ,b.name AS equ_name,b.equ_number ")
.append("FROM equ_gather g ") .append("FROM equ_gather g ")
.append("JOIN equ_base b ON g.equ_id = b.id ") .append("JOIN equ_base b ON g.equ_id = b.id ")
.append("JOIN equ_type t ON b.equ_type = t.id ") // ★ 新增关联 .append("JOIN equ_type t ON b.equ_type = t.id ") // ★ 新增关联
@ -153,7 +154,7 @@ public class AlertRuleServiceImpl implements IAlertRuleService
.append(buildConditionsSql(conditions)); .append(buildConditionsSql(conditions));
} else { } else {
// 其他表,需要连 equ_gather → equ_base → equ_type // 其他表,需要连 equ_gather → equ_base → equ_type
sql.append("src.*, g.equ_id, t.name AS equ_type,b.name AS equ_name ") sql.append("src.*, g.equ_id, t.name AS equ_type,b.name AS equ_name,b.equ_number ")
.append("FROM ").append(rule.getTableName()).append(" src ") .append("FROM ").append(rule.getTableName()).append(" src ")
.append("JOIN equ_gather g ON src.equ_gather_id = g.id ") .append("JOIN equ_gather g ON src.equ_gather_id = g.id ")
.append("JOIN equ_base b ON g.equ_id = b.id ") .append("JOIN equ_base b ON g.equ_id = b.id ")
@ -316,7 +317,7 @@ public class AlertRuleServiceImpl implements IAlertRuleService
@Override @Override
public AlertRule selectAlertRuleById(Long id) public AlertRule selectAlertRuleById(Long id)
{ {
return alertRuleMapper.selectAlertRuleById(id); return alertRuleMapper.selectAlertRuleByToId(id);
} }
/** /**
@ -326,7 +327,7 @@ public class AlertRuleServiceImpl implements IAlertRuleService
* @return 请填写功能名称 * @return 请填写功能名称
*/ */
@Override @Override
public List<AlertRule> selectAlertRuleList(AlertRule alertRule) public List<AlertRuleVo> selectAlertRuleList(AlertRule alertRule)
{ {
return alertRuleMapper.selectAlertRuleList(alertRule); return alertRuleMapper.selectAlertRuleList(alertRule);
} }

@ -1,16 +1,13 @@
package com.alops.system.service.impl; package com.alops.system.service.impl;
import java.util.Date; import java.math.BigDecimal;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.UUID;
import com.alops.common.utils.SecurityUtils; import com.alops.common.utils.SecurityUtils;
import com.alops.system.domain.EquBase; import com.alops.system.domain.EquBase;
import com.alops.system.domain.EquSupplier;
import com.alops.system.domain.EquType;
import com.alops.system.domain.dto.EquBaseQueryDto; import com.alops.system.domain.dto.EquBaseQueryDto;
import com.alops.system.domain.vo.dropDownVo; import com.alops.system.domain.vo.dropDownVo;
import com.alops.system.domain.vo.equipmentAssessmentVo;
import com.alops.system.domain.vo.imageVo; import com.alops.system.domain.vo.imageVo;
import com.alops.system.domain.dto.*; import com.alops.system.domain.dto.*;
import com.alops.system.domain.vo.queryEquBaseVO; import com.alops.system.domain.vo.queryEquBaseVO;
@ -55,6 +52,54 @@ public class EquBaseServiceImpl implements IEquBaseService
return equSupplierMapper.selectEquSupDropDown(); return equSupplierMapper.selectEquSupDropDown();
} }
//设备评估信息
@Override
public List<equipmentAssessmentVo> getDeviceIAssessmentnfo(){
List<equipmentAssessmentDto> equAsstDtoList = equBaseMapper.getEquipmentAssessmentList();
List<equipmentAssessmentVo> resultList = new ArrayList<>();
for (equipmentAssessmentDto dto : equAsstDtoList) {
equipmentAssessmentVo vo = new equipmentAssessmentVo();
vo.setId(dto.getId());
vo.setEquNumber(dto.getEquNumber());
vo.setName(dto.getName());
vo.setLocation(dto.getLocation());
vo.setEquType(dto.getEquType());
vo.setDeviceLevel(dto.getDeviceLevel());
// 四项指标
String cpuStatus = checkStatus(dto.getCpuUtilization(), 80, 90, 95);
String memoryStatus = checkStatus(dto.getMemoryUtilization(), 80, 90, 95);
String temperatureStatus = checkTemperatureStatus(dto.getTemperature());
String healthStatus = checkHealthStatus(dto.getHealth());
vo.setCpuStatus(cpuStatus);
vo.setMemoryStatus(memoryStatus);
vo.setTemperatureStatus(temperatureStatus);
vo.setHealthStatus(healthStatus);
// 风险等级 = 四项指标中最严重的
int riskLevel = Math.max(
Math.max(getRisk(cpuStatus), getRisk(memoryStatus)),
Math.max(getRisk(temperatureStatus), getRisk(healthStatus))
);
vo.setRiskGrade(switch (riskLevel) {
case 1 -> "无风险";
case 2 -> "低";
case 3 -> "中";
case 4 -> "高";
default -> "未知";
});
resultList.add(vo);
}
return resultList;
}
@Autowired @Autowired
private EquInterfaceMapper interfaceMapper; private EquInterfaceMapper interfaceMapper;
/** /**
@ -110,14 +155,16 @@ public class EquBaseServiceImpl implements IEquBaseService
MonitorHistoryDto dto = new MonitorHistoryDto(); MonitorHistoryDto dto = new MonitorHistoryDto();
for (Map<String, Object> row : rows) { for (Map<String, Object> row : rows) {
dto.getTemperatureList().add(row.get("temperature_value") != null ? ((Number) row.get("temperature_value")).floatValue() : null); dto.getTemperatureList().add(row.get("temperature_value") != null ? ((Number) row.get("temperature_value")).floatValue() : null);
dto.getInvoltageList().add(row.get("involtage_value") != null ? ((Number) row.get("involtage_value")).floatValue() : null); dto.getMemoryList().add(row.get("memory_value") != null ? ((Number) row.get("memory_value")).floatValue() : null);
dto.getOutvoltageList().add(row.get("outvoltage_value") != null ? ((Number) row.get("outvoltage_value")).floatValue() : null); dto.getCpuList().add(row.get("cpu_value") != null ? ((Number) row.get("cpu_value")).floatValue() : null);
dto.getTimeList().add(row.get("gather_time").toString()); dto.getHealthList().add(row.get("health_value") != null ? ((Number) row.get("health_value")).floatValue() : null);
dto.getTimeList().add(row.get("gather_time") != null ? row.get("gather_time").toString() : null);
} }
return dto; return dto;
} }
/** /**
* 查询设备基本信息列表 * 查询设备基本信息列表
* *
@ -131,21 +178,101 @@ public class EquBaseServiceImpl implements IEquBaseService
} }
/** /**
* 查询多台显示界面的单独信息 * 查询多台设备的最新监测信息
**/
@Override
public List<MonitorListDto> selectEquMonitorListPaged() {
return equBaseMapper.selectEquMonitorListPaged();
}
/**
* 查询多台设备的最新监测信息首页展示
**/ **/
@Override @Override
public List<MonitorListDto> selectEquMonitorList(EquBaseQueryDto equBaseQueryDto) { public List<EquMonitorHomeDto> selectLatestEquMonitorList() {
return equBaseMapper.selectEquMonitorList(equBaseQueryDto); return equBaseMapper.selectLatestEquMonitorList();
} }
/** /**
* 设备类型分类统计信息 * 设备类型分类统计信息
**/ **/
@Override @Override
public List<MonitorStatisticDto> selectEquStatisticByType() { public List<MonitorStatisticDto> selectEquStatisticByType() {
return equBaseMapper.selectEquStatisticByType(); List<MonitorStatisticDto> list = equBaseMapper.selectEquStatisticByType();
if (list == null || list.isEmpty()) {
return list;
}
// 计算每种类型的数量
int totalCount = 0;
for (MonitorStatisticDto dto : list) {
int count = (dto.getDevices() != null) ? dto.getDevices().size() : 0;
dto.setCount(count);
totalCount += count;
}
// 计算百分比
for (MonitorStatisticDto dto : list) {
if (totalCount > 0) {
double percent = (dto.getCount() * 100.0) / totalCount;
dto.setPercentage(Math.round(percent * 100.0) / 100.0); // 保留两位小数
} else {
dto.setPercentage(0.0);
}
}
this.totalDeviceCount = totalCount; // 注意:你可以在 service 中定义字段存储
return list;
} }
// 在类中增加:
private int totalDeviceCount;
public int getTotalDeviceCount() {
return totalDeviceCount;
}
/** 通用百分比指标判断(CPU/内存) */
private String checkStatus(BigDecimal val, double healthy, double good, double average) {
if (val == null) return "未知";
double v = val.doubleValue();
if (v < healthy) return "健康";
if (v < good) return "良好";
if (v < average) return "一般";
return "需维护";
}
/** 温度判断 */
private String checkTemperatureStatus(BigDecimal temp) {
if (temp == null) return "未知";
double val = temp.doubleValue();
if (val >= 25 && val <= 45) return "健康";
if ((val >= 20 && val < 25) || (val > 45 && val <= 50)) return "良好";
if ((val >= 16 && val < 20) || (val > 50 && val <= 55)) return "一般";
return "需维护";
}
/** 健康度判断 */
private String checkHealthStatus(BigDecimal health) {
if (health == null) return "未知";
return switch (health.intValue()) {
case 1 -> "健康";
case 2 -> "良好";
case 3 -> "一般";
case 4 -> "需维护";
default -> "未知";
};
}
/** 风险等级映射:健康=1,良好=2,一般=3,需维护=4 */
private int getRisk(String status) {
return switch (status) {
case "健康" -> 1;
case "良好" -> 2;
case "一般" -> 3;
case "需维护" -> 4;
default -> 0;
};
}
/** /**
@ -160,6 +287,7 @@ public class EquBaseServiceImpl implements IEquBaseService
if (equBase.getCreateDate() == null) { if (equBase.getCreateDate() == null) {
equBase.setCreateDate(new Date()); equBase.setCreateDate(new Date());
} }
equBase.setId(UUID.randomUUID().toString());
equBase.setCreateBy(SecurityUtils.getLoginUser().getUserId()); equBase.setCreateBy(SecurityUtils.getLoginUser().getUserId());
return equBaseMapper.insertEquBase(equBase); return equBaseMapper.insertEquBase(equBase);
} }

@ -59,7 +59,8 @@ public class EquManuServiceImpl implements IEquManuService
{ {
equManu.setId(UUID.randomUUID().toString()); equManu.setId(UUID.randomUUID().toString());
equManu.setCreateDate(new Date()); equManu.setCreateDate(new Date());
Long userId = SecurityUtils.getLoginUser().getUserId(); String userName = SecurityUtils.getLoginUser().getUser().getUserName();
equManu.setCreateBy(userName);
return equManuMapper.insertEquManu(equManu); return equManuMapper.insertEquManu(equManu);
} }
@ -72,7 +73,8 @@ public class EquManuServiceImpl implements IEquManuService
@Override @Override
public int updateEquManu(EquManu equManu) public int updateEquManu(EquManu equManu)
{ {
Long userId = SecurityUtils.getLoginUser().getUserId(); String userName = SecurityUtils.getLoginUser().getUser().getUserName();
equManu.setCreateBy(userName);
return equManuMapper.updateEquManu(equManu); return equManuMapper.updateEquManu(equManu);
} }

@ -2,8 +2,12 @@ package com.alops.system.service.impl;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID;
import com.alops.common.utils.DateUtils; import com.alops.common.utils.DateUtils;
import com.alops.common.utils.SecurityUtils;
import com.alops.system.domain.dto.EquSupplierAddDto;
import com.alops.system.domain.dto.EquSupplierUpdateDto;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.alops.system.mapper.EquSupplierMapper; import com.alops.system.mapper.EquSupplierMapper;
@ -53,26 +57,52 @@ public class EquSupplierServiceImpl implements IEquSupplierService
/** /**
* 新增请填写功能名称 * 新增请填写功能名称
* *
* @param equSupplier 请填写功能名称
* @return 结果 * @return 结果
*/ */
@Override @Override
public int insertEquSupplier(EquSupplier equSupplier) public int insertEquSupplier(EquSupplierAddDto dto)
{ {
equSupplier.setCreateTime(new Date()); EquSupplier equSupplier = new EquSupplier();
// DTO 转换到实体
equSupplier.setId(UUID.randomUUID().toString()); // 自动生成 id
equSupplier.setName(dto.getName());
equSupplier.setDescription(dto.getDescription());
equSupplier.setContactBy(dto.getContactBy());
equSupplier.setContactWay(dto.getContactWay());
equSupplier.setCreateTime(new Date()); // 自动生成创建时间
equSupplier.setStatus(dto.getStatus());
String userName = SecurityUtils.getLoginUser().getUser().getUserName();
equSupplier.setCreateBy(userName);
return equSupplierMapper.insertEquSupplier(equSupplier); return equSupplierMapper.insertEquSupplier(equSupplier);
} }
/** /**
* 修改请填写功能名称 * 修改请填写功能名称
* *
* @param equSupplier 请填写功能名称
* @return 结果 * @return 结果
*/ */
@Override @Override
public int updateEquSupplier(EquSupplier equSupplier) public int updateEquSupplier(EquSupplierUpdateDto updateDto) {
{ // 将 DTO 转换成 Entity
EquSupplier equSupplier = new EquSupplier();
equSupplier.setId(updateDto.getId());
equSupplier.setName(updateDto.getName());
equSupplier.setDescription(updateDto.getDescription());
equSupplier.setContactBy(updateDto.getContactBy());
equSupplier.setContactWay(updateDto.getContactWay());
equSupplier.setStatus(updateDto.getStatus());
// 后端自动设置修改时间
equSupplier.setCreateTime(new Date());
String userName = SecurityUtils.getLoginUser().getUser().getUserName();
equSupplier.setCreateBy(userName);
return equSupplierMapper.updateEquSupplier(equSupplier); return equSupplierMapper.updateEquSupplier(equSupplier);
} }

@ -56,7 +56,8 @@ public class EquTypeServiceImpl implements IEquTypeService
public int insertEquType(EquType equType) public int insertEquType(EquType equType)
{ {
equType.setId(UUID.randomUUID().toString()); equType.setId(UUID.randomUUID().toString());
Long userId = SecurityUtils.getLoginUser().getUserId(); String userName = SecurityUtils.getLoginUser().getUser().getUserName();
equType.setCreateBy(userName);
return equTypeMapper.insertEquType(equType); return equTypeMapper.insertEquType(equType);
} }
@ -69,7 +70,8 @@ public class EquTypeServiceImpl implements IEquTypeService
@Override @Override
public int updateEquType(EquType equType) public int updateEquType(EquType equType)
{ {
Long userId = SecurityUtils.getLoginUser().getUserId(); String userName = SecurityUtils.getLoginUser().getUser().getUserName();
equType.setCreateBy(userName);
return equTypeMapper.updateEquType(equType); return equTypeMapper.updateEquType(equType);
} }

@ -5,10 +5,7 @@ import java.sql.SQLOutput;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.ExecutionException; import java.util.concurrent.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.alops.common.core.domain.AjaxResult; import com.alops.common.core.domain.AjaxResult;
@ -25,6 +22,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -57,69 +55,117 @@ public class ScheduleRulesServiceImpl implements IScheduleRulesService {
@Autowired @Autowired
private MemoryToolService memoryToolService; private MemoryToolService memoryToolService;
@Autowired
private IAlertSenderService iAlertSenderService;
private static final Logger log = LoggerFactory.getLogger(ScheduleRulesServiceImpl.class); private static final Logger log = LoggerFactory.getLogger(ScheduleRulesServiceImpl.class);
@Override
public AjaxResult executeRule(ScheduleRules newRule) throws SchedulerException, ExecutionException, InterruptedException {
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Boolean checkRunningOrWaitingRules() throws SchedulerException {
// 1. 获取所有正在执行(1)和待执行(0)的规则
List<ScheduleRules> runningOrWaiting = scheduleRulesMapper.selectList(); List<ScheduleRules> runningOrWaiting = scheduleRulesMapper.selectList();
if (runningOrWaiting!=null) { if (runningOrWaiting!=null) {
for (ScheduleRules rule : runningOrWaiting) { for (ScheduleRules rule : runningOrWaiting) {
switch (rule.getStatus()) { switch (rule.getStatus()) {
case 1: // 正在执行 case 1: // 正在执行
log.info("规则[{}]:正在执行上一个任务,等待上一个任务完成……", rule.getId()); log.info("规则[{}]:正在执行上一个任务,等待上一个任务完成……", rule.getId());
waitTaskFinish(rule.getId());
log.info("规则[{}]:完成上一个任务任务,开始新的任务…", rule.getId());
if (rule.getRuleType() == 2 || rule.getRuleType() == 1) { if (rule.getRuleType() == 2 || rule.getRuleType() == 1) {
rule.setStatus(2); rule.setStatus(2);
} else if (rule.getRuleType() == 0) { } else if (rule.getRuleType() == 0) {
log.info("改变状态为4");
rule.setStatus(4); rule.setStatus(4);
} }
scheduleRulesMapper.updateScheduleRules(rule); scheduleRulesMapper.updateScheduleRules(rule);
break; return true;
case 0: // 待执行 case 0: // 待执行
if (rule.getRuleType() == 0 || rule.getRuleType() == 1) { if (rule.getRuleType() == 0 || rule.getRuleType() == 1) {
quartzService.deleteJob(rule.getId()); quartzService.deleteJob(rule.getId());
} }
rule.setStatus(4); rule.setStatus(4);
scheduleRulesMapper.updateScheduleRules(rule); scheduleRulesMapper.updateScheduleRules(rule);
break; return false;
default: default:
break; return true;
} }
} }
} }
// 2. 执行新规则 return false;
}
//首先存入规则在执行 @Override
Date now = new Date(); public Boolean executeRule(ScheduleRules newRule) throws SchedulerException, ExecutionException, InterruptedException {
Long userId = SecurityUtils.getLoginUser().getUserId();
newRule.setCreatedBy(userId);
newRule.setCreatedAt(now); // // 1. 获取所有正在执行(1)和待执行(0)的规则
newRule.setStatus(0); // List<ScheduleRules> runningOrWaiting = scheduleRulesMapper.selectList();
scheduleRulesMapper.insertScheduleRules(newRule); // if (runningOrWaiting!=null) {
switch (newRule.getRuleType().toString()) { // for (ScheduleRules rule : runningOrWaiting) {
case "2": // 立即执行 // switch (rule.getStatus()) {
newRule.setStatus(1); // case 1: // 正在执行
scheduleRulesMapper.updateScheduleRules(newRule); // log.info("规则[{}]:正在执行上一个任务,等待上一个任务完成……", rule.getId());
try { // waitTaskFinish(rule.getId());
executeImmediately(); // log.info("规则[{}]:完成上一个任务任务,开始新的任务…", rule.getId());
newRule.setStatus(2); // if (rule.getRuleType() == 2 || rule.getRuleType() == 1) {
scheduleRulesMapper.updateScheduleRules(newRule); // rule.setStatus(2);
return AjaxResult.success("立即执行任务成功:"); // 异常会抛出,前端收到 // } else if (rule.getRuleType() == 0) {
} catch (Exception e) { // rule.setStatus(4);
// }
newRule.setStatus(3); // scheduleRulesMapper.updateScheduleRules(rule);
// break;
// case 0: // 待执行
// if (rule.getRuleType() == 0 || rule.getRuleType() == 1) {
// quartzService.deleteJob(rule.getId());
// }
// rule.setStatus(4);
// scheduleRulesMapper.updateScheduleRules(rule);
// break;
// default:
// break;
// }
// }
// }
// 2. 执行新规则
try {
Date now = new Date();
Long userId = SecurityUtils.getLoginUser().getUserId();
// 1. 初始化规则
newRule.setCreatedBy(userId);
newRule.setCreatedAt(now);
newRule.setStatus(0);
scheduleRulesMapper.insertScheduleRules(newRule); // 插入成功与否决定返回值
switch (newRule.getRuleType().toString()) {
case "2": // 立即执行
newRule.setStatus(1); // 执行中
scheduleRulesMapper.updateScheduleRules(newRule); scheduleRulesMapper.updateScheduleRules(newRule);
// 只捕获立即执行异常
return AjaxResult.error("立即执行任务失败:" + e.getMessage());
}
// 异步立即执行采集任务
CompletableFuture.runAsync(() -> {
try {
executeImmediately(); // 实际采集逻辑
newRule.setStatus(2); // 执行成功
scheduleRulesMapper.updateScheduleRules(newRule);
String content = String.format("立即任务 [%s] 执行完成", newRule.getRuleName());
iAlertSenderService.sendInternalMessage(content, "2");
} catch (Exception e) {
newRule.setStatus(3); // 执行失败
scheduleRulesMapper.updateScheduleRules(newRule);
String content = String.format("立即任务 [%s] 执行失败:%s", newRule.getRuleName(), e.getMessage());
try {
iAlertSenderService.sendInternalMessage(content, "2");
} catch (Exception ne) {
log.error("发送站内信失败: {}", ne.getMessage(), ne);
}
}
});
break;
case "1": // 固定时间 case "1": // 固定时间
newRule.setStatus(0); newRule.setStatus(0);
scheduleRulesMapper.updateScheduleRules(newRule); scheduleRulesMapper.updateScheduleRules(newRule);
@ -136,10 +182,14 @@ public class ScheduleRulesServiceImpl implements IScheduleRulesService {
quartzService.createOrUpdateJob(newRule); quartzService.createOrUpdateJob(newRule);
} }
break; break;
default: default:
throw new IllegalArgumentException("Unsupported rule type"); throw new IllegalArgumentException("Unsupported rule type");
}
return true; // 插入和调度成功
} catch (Exception e) {
log.error("规则设置失败: {}", e.getMessage(), e);
return false; // 插入或调度失败
} }
return null;
} }
/** /**
@ -163,7 +213,7 @@ public class ScheduleRulesServiceImpl implements IScheduleRulesService {
Map<String, List<EquOid>> oidMap = new HashMap<>(); Map<String, List<EquOid>> oidMap = new HashMap<>();
for (EquBase dev : devices) { for (EquBase dev : devices) {
oidMap.put(dev.getManufacture(), equOidMapper.findByManuIdAndStatus(dev.getManufacture())); oidMap.put(dev.getEquManuId(), equOidMapper.findByManuIdAndStatus(dev.getEquManuId()));
} }
ExecutorService executor = Executors.newFixedThreadPool(10); ExecutorService executor = Executors.newFixedThreadPool(10);
@ -172,7 +222,7 @@ public class ScheduleRulesServiceImpl implements IScheduleRulesService {
for (EquBase device : devices) { for (EquBase device : devices) {
futures.add(executor.submit(() -> { futures.add(executor.submit(() -> {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
List<EquOid> oids = oidMap.getOrDefault(device.getManufacture(), Collections.emptyList()); List<EquOid> oids = oidMap.getOrDefault(device.getEquManuId(), Collections.emptyList());
Map<String, Object> snmpResults = snmpService.query(device.getIp(), oids); Map<String, Object> snmpResults = snmpService.query(device.getIp(), oids);
long afterSnmp = System.currentTimeMillis(); long afterSnmp = System.currentTimeMillis();
System.out.println("SNMP查询耗时: " + (afterSnmp - start) + " ms"); System.out.println("SNMP查询耗时: " + (afterSnmp - start) + " ms");
@ -243,6 +293,7 @@ public class ScheduleRulesServiceImpl implements IScheduleRulesService {
// 执行最新预警 // 执行最新预警
iAlertLaunchService.executeImmediateAlerts(); iAlertLaunchService.executeImmediateAlerts();
log.info("采集完一次!!!");
return result; return result;
} }

@ -19,7 +19,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="handleTime" column="handle_time" /> <result property="handleTime" column="handle_time" />
<result property="status" column="status" /> <result property="status" column="status" />
<result property="batch" column="batch" /> <result property="batch" column="batch" />
<result property="message" column="message" />
</resultMap> </resultMap>
<select id="selectMaxBatch" resultType="integer"> <select id="selectMaxBatch" resultType="integer">
@ -30,12 +30,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<insert id="batchInsert" parameterType="java.util.List"> <insert id="batchInsert" parameterType="java.util.List">
INSERT INTO alert_message INSERT INTO alert_message
(equ_id, type, equ_type, solution, level, occur_time, handler, handle_time, status,batch) (equ_id, type, equ_type, solution, level, occur_time, handler, handle_time, status,batch,message)
VALUES VALUES
<foreach collection="list" item="msg" separator=","> <foreach collection="list" item="msg" separator=",">
(#{msg.equId},#{msg.type}, #{msg.equType}, (#{msg.equId},#{msg.type}, #{msg.equType},
#{msg.solution}, #{msg.level}, #{msg.occurTime}, #{msg.solution}, #{msg.level}, #{msg.occurTime},
#{msg.handler}, #{msg.handleTime}, #{msg.status}, #{msg.batch}) #{msg.handler}, #{msg.handleTime}, #{msg.status}, #{msg.batch}, #{msg.message})
</foreach> </foreach>
</insert> </insert>
@ -52,13 +52,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
am.handler, am.handler,
am.handle_time, am.handle_time,
am.status, am.status,
am.batch am.batch,
am.message
FROM alert_message am FROM alert_message am
LEFT JOIN equ_base eb ON am.equ_id = eb.id LEFT JOIN equ_base eb ON am.equ_id = eb.id
</sql> </sql>
<sql id="selectAlertMessageVoJoinGather"> <sql id="selectAlertMessageVoJoinGather">
select a.id, g.equ_id, type, equ_type solution, level, occur_time, handler, handle_time, status,batch from alert_message a LEFT JOIN equ_gather g ON a.equ_id = g.equ_id select a.id, g.equ_id, type, equ_type, solution, level, occur_time, handler, handle_time, status,batch,message from alert_message a LEFT JOIN equ_gather g ON a.equ_id = g.equ_id
</sql> </sql>
<select id="selectAlertMessageList" parameterType="AlertDto" resultMap="AlertMessageResult"> <select id="selectAlertMessageList" parameterType="AlertDto" resultMap="AlertMessageResult">
@ -83,7 +84,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<!-- 按 batch 从大到小排序 --> <!-- 按 batch 从大到小排序 -->
ORDER BY am.batch DESC ORDER BY am.batch DESC
</select> </select>
<!-- 查询最新预警信息(按时间排序,取前N条) -->
<select id="selectStaticAlertMessageList" resultType="homeEquAlertMessageVo">
SELECT
a.level,
a.occur_time AS occurTime,
a.status,
a.message,
e.name,
e.location
FROM alert_message a
LEFT JOIN equ_base e ON a.equ_id = e.id
ORDER BY a.occur_time DESC
</select>
<select id="selectAlertMessageById" parameterType="Long" resultMap="AlertMessageResult"> <select id="selectAlertMessageById" parameterType="Long" resultMap="AlertMessageResult">
<include refid="selectAlertMessageVo"/> <include refid="selectAlertMessageVo"/>
where am.id = #{id} where am.id = #{id}

@ -31,18 +31,44 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectAlertRuleVo"> <sql id="selectAlertRuleVo">
SELECT SELECT
ar.id, ar.id,
ar.rule_name, ar.rule_name AS ruleName,
ar.severity, ar.severity,
ar.alert_way, ar.alert_way AS alertWay,
ar.alert_station, ar.alert_station AS alertStation,
ar.description, ar.description,
ar.enable, ar.enable,
ar.create_time, ar.create_time as createTime,
ar.update_time, ar.update_time as updateTime,
su1.user_name AS create_by, su1.user_name AS createBy,
su2.user_name AS update_by, su2.user_name AS updateBy,
ar.table_name, ar.table_name as tableName,
ar.alert_sql, ar.alert_sql AS alertSql,
ar.alert_template AS alertTemplate,
ar.type,
ac.param_name AS paramName,
ac.operator,
ac.compare_value AS compareValue
FROM alert_rule ar
LEFT JOIN sys_user su1 ON ar.create_by = su1.user_id
LEFT JOIN sys_user su2 ON ar.update_by = su2.user_id
LEFT JOIN alert_rule_condition ac ON ar.id = ac.alert_rule_id
</sql>
<sql id="selectAlertRuleVo2">
SELECT
ar.id,
ar.rule_name ,
ar.severity,
ar.alert_way ,
ar.alert_station ,
ar.description,
ar.enable,
ar.create_time ,
ar.update_time ,
su1.user_name as create_by,
su2.user_name as update_by,
ar.table_name ,
ar.alert_sql ,
ar.alert_template, ar.alert_template,
ar.type ar.type
FROM alert_rule ar FROM alert_rule ar
@ -50,7 +76,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN sys_user su2 ON ar.update_by = su2.user_id LEFT JOIN sys_user su2 ON ar.update_by = su2.user_id
</sql> </sql>
<select id="selectAlertRuleList" parameterType="AlertRule" resultMap="AlertRuleResult"> <select id="selectAlertRuleList" parameterType="AlertRule" resultType="alertRuleVo">
<include refid="selectAlertRuleVo"/> <include refid="selectAlertRuleVo"/>
<where> <where>
<if test="ruleName != null and ruleName != ''"> and ar.rule_name like concat('%', #{ruleName}, '%')</if> <if test="ruleName != null and ruleName != ''"> and ar.rule_name like concat('%', #{ruleName}, '%')</if>
@ -65,9 +91,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectAlertRuleById" parameterType="Long" resultMap="AlertRuleResult"> <select id="selectAlertRuleById" parameterType="Long" resultType="AlertRuleVo">
<include refid="selectAlertRuleVo"/> <include refid="selectAlertRuleVo"/>
where id = #{id} where ar.id = #{id}
</select>
<select id="selectAlertRuleByToId" parameterType="Long" resultMap="AlertRuleResult">
<include refid="selectAlertRuleVo2"/>
where ar.id = #{id}
</select> </select>
<insert id="insertAlertRule" parameterType="AlertRule" useGeneratedKeys="true" keyProperty="id"> <insert id="insertAlertRule" parameterType="AlertRule" useGeneratedKeys="true" keyProperty="id">

@ -9,9 +9,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="name" column="name" /> <result property="name" column="name" />
<result property="version" column="version" /> <result property="version" column="version" />
<result property="ip" column="ip" /> <result property="ip" column="ip" />
<result property="manufacture" column="manufacture" /> <result property="equManuId" column="manufacture" />
<result property="location" column="location" /> <result property="location" column="location" />
<result property="equType" column="equ_type" /> <result property="equTypeId" column="equ_type" />
<result property="inCharge" column="in_charge" /> <result property="inCharge" column="in_charge" />
<result property="installDate" column="install_date" /> <result property="installDate" column="install_date" />
<result property="lifeCycle" column="life_cycle" /> <result property="lifeCycle" column="life_cycle" />
@ -24,29 +24,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="supplierId" column="supplier_id" /> <result property="supplierId" column="supplier_id" />
<result property="gatherFrequency" column="gather_frequency" /> <result property="gatherFrequency" column="gather_frequency" />
<result property="equImage" column="equ_image" /> <result property="equImage" column="equ_image" />
<result property="repairFrequency" column="repair_frequency" /> <result property="equNumber" column="equ_number" />
<result property="repairCost" column="repair_cost" />
<result property="fanSpeed" column="fan_speed"/>
<result property="cpuUtilization" column="cpu_utilization"/>
<result property="memoryUtilization" column="memory_utilization"/>
<result property="health" column="health"/>
<result property="contWorkPeriod" column="cont_work_period"/>
<association property="manufactureVO" columnPrefix="equ_manu_" autoMapping="true" /> <association property="manufactureVO" columnPrefix="equ_manu_" autoMapping="true" />
<association property="equTypeVO" columnPrefix="equ_type_" autoMapping="true" /> <association property="equTypeVO" columnPrefix="equ_type_" autoMapping="true" />
<collection property="temperatureList" javaType="java.util.ArrayList" ofType="java.lang.Float">
<result column="temperature_value"/>
</collection>
<collection property="involtageList" javaType="java.util.ArrayList" ofType="java.lang.Float">
<result column="involtage_value"/>
</collection>
<collection property="outvoltageList" javaType="java.util.ArrayList" ofType="java.lang.Float">
<result column="outvoltage_value"/>
</collection>
<!-- <association property="manufacture" columnPrefix="equ_manu_" autoMapping="true" />-->
</resultMap> </resultMap>
<resultMap id="EquMonitorResult" type="com.alops.system.domain.vo.EquMonitorVO"> <resultMap id="EquMonitorResult" type="com.alops.system.domain.vo.EquMonitorVO">
<result property="id" column="id" /> <result property="id" column="id" />
@ -57,23 +43,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="location" column="location" /> <result property="location" column="location" />
<result property="equType" column="equ_type" /> <result property="equType" column="equ_type" />
<result property="inCharge" column="in_charge" /> <result property="inCharge" column="in_charge" />
<result property="releaseDate" column="release_date" />
<result property="installDate" column="install_date" /> <result property="installDate" column="install_date" />
<result property="lifeCycle" column="life_cycle" /> <result property="lifeCycle" column="life_cycle" />
<result property="serviceTime" column="service_time" />
<result property="warranty" column="warranty" /> <result property="warranty" column="warranty" />
<result property="createBy" column="create_by" /> <result property="createBy" column="create_by" />
<result property="createDate" column="create_date" /> <result property="createDate" column="create_date" />
<result property="updateBy" column="update_by" />
<result property="updateDate" column="update_date" />
<result property="status" column="status" /> <result property="status" column="status" />
<result property="failureFrequency" column="failure_frequency" /> <result property="failureFrequency" column="failure_frequency" />
<result property="repairFrequency" column="repair_frequency" />
<result property="repairCost" column="repair_cost" />
<result property="fanSpeed" column="fan_speed"/> <result property="fanSpeed" column="fan_speed"/>
<result property="cpuUtilization" column="cpu_utilization"/> <result property="cpuUtilization" column="cpu_utilization"/>
<result property="memoryUtilization" column="memory_utilization"/> <result property="memoryUtilization" column="memory_utilization"/>
<result property="health" column="health"/> <result property="health" column="health"/>
<result property="equImage" column="equ_image" />
<result property="equNumber" column="equ_number" />
<result property="contWorkPeriod" column="cont_work_period"/> <result property="contWorkPeriod" column="cont_work_period"/>
<association property="manufactureVO" columnPrefix="equ_manu_" autoMapping="true" /> <association property="manufactureVO" columnPrefix="equ_manu_" autoMapping="true" />
<association property="equTypeVO" columnPrefix="equ_type_" autoMapping="true" /> <association property="equTypeVO" columnPrefix="equ_type_" autoMapping="true" />
@ -91,7 +76,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectEquBaseVo"> <sql id="selectEquBaseVo">
select id, name, version, ip, manufacture, location, equ_type, in_charge, install_date, life_cycle, warranty, create_by, create_date, status, device_level, supplier_id from equ_base select id,equ_number, name, version, ip, manufacture, location, equ_type, in_charge, install_date, life_cycle, warranty, create_by, create_date, status, device_level, supplier_id from equ_base
</sql> </sql>
@ -105,6 +90,45 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update> </update>
<select id="getEquipmentAssessmentList"
resultType="com.alops.system.domain.dto.equipmentAssessmentDto">
SELECT
b.id AS id,
b.equ_number AS equNumber,
b.name AS name,
b.location AS location,
t.name AS equType, -- 从 equ_type 表取类型名称
b.device_level AS deviceLevel,
-- 从 equ_gather 最新一条记录中取数据
g.health AS health,
g.temperature AS temperature,
g.cpu_utilization AS cpuUtilization,
g.memory_utilization AS memoryUtilization
FROM equ_base b
LEFT JOIN equ_type t
ON b.equ_type = t.id
LEFT JOIN (
SELECT eg1.*
FROM equ_gather eg1
INNER JOIN (
SELECT equ_id, MAX(gather_time) AS max_time
FROM equ_gather
GROUP BY equ_id
) eg2
ON eg1.equ_id = eg2.equ_id AND eg1.gather_time = eg2.max_time
) g
ON b.id = g.equ_id
WHERE b.status = 1
ORDER BY b.id
</select>
<select id="findEquBaseList" resultMap="EquBaseResult"> <select id="findEquBaseList" resultMap="EquBaseResult">
<include refid="selectEquBaseVo"/> <include refid="selectEquBaseVo"/>
<where> <where>
@ -114,13 +138,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<!-- 查询列 --> <!-- 查询列 -->
<sql id="selectEquBaseVo2"> <sql id="selectEquBaseVo2">
b.id AS id, b.id AS id,
b.equ_number AS equNumber,
b.name AS name, b.name AS name,
b.version AS version, b.version AS version,
b.ip AS ip, b.ip AS ip,
m.name AS manuName, b.manufacture AS equManuId,
m.name AS manufacture,
b.supplier_id AS supplierId,
s.name AS supplierName, s.name AS supplierName,
b.location AS location, b.location AS location,
b.equ_type AS equTypeId,
t.name AS equType, t.name AS equType,
b.in_charge AS inCharge, b.in_charge AS inCharge,
b.install_date AS installDate, b.install_date AS installDate,
@ -130,7 +158,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
b.create_date AS createDate, b.create_date AS createDate,
b.status AS status, b.status AS status,
b.device_level AS deviceLevel, b.device_level AS deviceLevel,
g.health AS health g.health AS health,
b.equ_image AS equImage
</sql> </sql>
<select id="selectEquBaseList" parameterType="equBaseQueryDto" resultType="com.alops.system.domain.vo.queryEquBaseVO"> <select id="selectEquBaseList" parameterType="equBaseQueryDto" resultType="com.alops.system.domain.vo.queryEquBaseVO">
@ -152,100 +181,141 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
) tmp ON eg.equ_id = tmp.equ_id AND eg.gather_time = tmp.max_time ) tmp ON eg.equ_id = tmp.equ_id AND eg.gather_time = tmp.max_time
) g ON b.id = g.equ_id ) g ON b.id = g.equ_id
<where> <where>
<if test="name != null and name != ''">
AND b.name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="location != null and location != ''">
AND b.location LIKE CONCAT('%', #{location}, '%')
</if>
<if test="minTime != null"> <if test="minTime != null">
AND b.create_date &gt;= #{minTime} AND b.create_date &gt;= #{minTime}
</if> </if>
<if test="maxTime != null"> <if test="maxTime != null">
AND b.create_date &lt;= #{maxTime} AND b.create_date &lt;= #{maxTime}
</if> </if>
<if test="status != null">
AND b.status = #{status}
</if>
</where> </where>
</select> </select>
<select id="selectEquMonitorList" parameterType="EquBaseQueryDto" resultType="MonitorListDto"> <select id="selectEquMonitorListPaged" resultType="MonitorListDto">
SELECT SELECT
b.id, c.id,
b.name, c.name,
b.version, c.ip,
b.device_level, c.equTypeId,
b.location, c.equTypeName,
b.status, c.equManuId,
g.cpu_utilization, c.equManuName,
g.health, c.version,
g.fan_speed, c.deviceLevel,
b.failure_frequency, c.location,
b.equ_image c.status,
FROM equ_base b c.cpuUtilization,
LEFT JOIN equ_gather g ON b.id = g.equ_id c.health,
<where> c.fanSpeed,
g.cpu_utilization is not null c.contWorkPeriod,
<if test="equType != null and equType != ''"> c.unhandledAlertCount,
AND b.equ_type = #{equType} c.AlertCount
</if> FROM (
<if test="equName != null and equName != ''"> SELECT
AND b.name LIKE concat('%', #{equName}, '%') b.id,
</if> b.name,
<if test="location != null and location != ''"> b.ip,
AND b.location = #{location} b.equ_type AS equTypeId,
</if> t.name AS equTypeName,
<if test="manufacture != null and manufacture != ''"> b.manufacture AS equManuId,
AND b.manufacture = #{manufacture} m.name AS equManuName,
</if> b.version,
<if test="inCharge != null"> b.device_level AS deviceLevel,
AND b.in_charge = #{inCharge} b.location,
</if> b.status,
<if test="status != null"> g.cpu_utilization AS cpuUtilization,
AND b.status = #{status} g.health,
</if> g.fan_speed AS fanSpeed,
<if test="minTime != null"> g.cont_work_period AS contWorkPeriod,
AND b.create_date <![CDATA[>=]]> #{minTime} (SELECT COUNT(1)
</if> FROM alert_message a
<if test="maxTime != null"> WHERE a.equ_id = b.id AND a.status = 'UNHANDLED') AS unhandledAlertCount,
AND b.create_date <![CDATA[<=]]> #{maxTime} (SELECT COUNT(1)
</if> FROM alert_message a
<if test="health != null"> WHERE a.equ_id = b.id ) AS AlertCount,
AND g.health <![CDATA[>=]]> #{health} ROW_NUMBER() OVER (PARTITION BY b.id ORDER BY g.gather_time DESC) AS rn
</if> FROM equ_base b
</where> LEFT JOIN equ_type t ON b.equ_type = t.id
ORDER BY g.gather_time desc limit 1 LEFT JOIN equ_manu m ON b.manufacture = m.id
LEFT JOIN equ_gather g ON b.id = g.equ_id
) c
WHERE c.rn = 1
ORDER BY c.id
</select> </select>
<select id="selectLatestEquMonitorList" resultType="com.alops.system.domain.dto.EquMonitorHomeDto">
SELECT
t.id,
t.equNumber,
t.name,
t.location,
t.cpuUtilization,
t.memoryUtilization,
t.temperature,
t.health,
t.contWorkPeriod,
t.gatherTime
FROM (
SELECT
b.id,
b.equ_number as equNumber,
b.name,
b.location,
g.cpu_utilization AS cpuUtilization,
g.memory_utilization AS memoryUtilization,
g.temperature,
g.health,
g.cont_work_period AS contWorkPeriod,
g.gather_time AS gatherTime,
ROW_NUMBER() OVER (PARTITION BY b.id ORDER BY g.gather_time DESC) AS rn
FROM equ_base b
LEFT JOIN equ_gather g ON b.id = g.equ_id
) t
WHERE t.rn = 1
ORDER BY t.name
</select>
<select id="selectEquMonitorById" parameterType="string" resultType="MonitorLastDto"> <select id="selectEquMonitorById" parameterType="string" resultType="MonitorLastDto">
SELECT SELECT
g.cont_work_period, g.cont_work_period AS contWorkPeriod,
b.equ_image AS equImage,
b.id, b.id,
b.equ_number as equNumber,
b.name, b.name,
b.version, b.version,
b.device_level, b.device_level AS deviceLevel,
t.name as equ_type, b.equ_type as equTypeId,
m.name as manufacture, t.name as equTypeName,
s.name as supplier_id, b.status,
#b.release_date,
b.manufacture as equManuId,
m.name as equManuName,
b.supplier_id as supplierId,
s.name as supplierName,
s.contact_by AS ContactBy,
s.contact_way AS ContactWay,
b.warranty, b.warranty,
m.contact_by as manufacture,
m.contact_way as manufacture,
b.ip, b.ip,
b.location, b.location,
b.install_date, b.install_date AS installDate,
#b.service_time, b.in_charge AS inCharge,
b.in_charge,
b.failure_frequency, (SELECT COUNT(1)
#b.repair_frequency, FROM alert_message a
#b.service_time/warranty AS aging, WHERE a.equ_id = b.id ) AS AlertCount,
g.fan_speed, -- 新增列:统计未处理告警数量
g.cpu_utilization, (SELECT COUNT(1)
g.memory_utilization, FROM alert_message a
g.health WHERE a.equ_id = b.id AND a.status = 'UNHANDLED') AS unhandledAlertCount,
g.fan_speed AS fanSpeed,
g.cpu_utilization AS cpuUtilization,
g.memory_utilization AS memoryUtilization,
g.temperature,
g.health,
g.vol_in AS volIn,
g.vol_out AS volOut
FROM equ_base b FROM equ_base b
LEFT JOIN equ_manu m ON b.manufacture = m.id LEFT JOIN equ_manu m ON b.manufacture = m.id
@ -259,11 +329,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY g.gather_time desc limit 1 ORDER BY g.gather_time desc limit 1
</select> </select>
<select id="selectEquMonitorByIdToList" parameterType="com.alops.system.domain.dto.EquBaseQueryDto" resultType="map"> SELECT <select id="selectEquMonitorByIdToList" parameterType="com.alops.system.domain.dto.EquBaseQueryDto" resultType="map">
SELECT
-- 从 equ_gather 表中获取需要填充到List中的数据 -- 从 equ_gather 表中获取需要填充到List中的数据
g.temperature AS temperature_value, g.temperature AS temperature_value,
g.vol_in AS involtage_value, g.memory_utilization AS memory_value,
g.vol_out AS outvoltage_value, g.cpu_utilization AS cpu_value,
g.health AS health_value,
g.gather_time AS gather_time g.gather_time AS gather_time
FROM equ_base b FROM equ_base b
@ -271,8 +343,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN equ_type t ON b.equ_type = t.id LEFT JOIN equ_type t ON b.equ_type = t.id
LEFT JOIN equ_gather g ON b.id = g.equ_id LEFT JOIN equ_gather g ON b.id = g.equ_id
where g.cpu_utilization is not null where b.id = #{id}
and b.id = #{id}
-- 添加时间范围约束 -- 添加时间范围约束
and g.gather_time BETWEEN #{minTime} AND #{maxTime} and g.gather_time BETWEEN #{minTime} AND #{maxTime}
@ -352,15 +423,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="name != null">name,</if> <if test="name != null">name,</if>
<if test="version != null">version,</if> <if test="version != null">version,</if>
<if test="ip != null">ip,</if> <if test="ip != null">ip,</if>
<if test="manufacture != null">manufacture,</if> <if test="equManuId != null">manufacture,</if>
<if test="location != null">location,</if> <if test="location != null">location,</if>
<if test="equType != null">equ_type,</if> <if test="equTypeId != null">equ_type,</if>
<if test="inCharge != null">in_charge,</if> <if test="inCharge != null">in_charge,</if>
<if test="installDate != null">install_date,</if> <if test="installDate != null">install_date,</if>
<if test="lifeCycle != null">life_cycle,</if> <if test="lifeCycle != null">life_cycle,</if>
<if test="warranty != null">warranty,</if> <if test="warranty != null">warranty,</if>
<if test="createBy != null">create_by,</if> <if test="createBy != null">create_by,</if>
<if test="createDate != null">create_date,</if> <if test="createDate != null">create_date,</if>
<if test="equNumber != null">equ_number,</if>
status, status,
<if test="equImage != null">equ_image,</if> <if test="equImage != null">equ_image,</if>
@ -374,18 +446,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="name != null">#{name},</if> <if test="name != null">#{name},</if>
<if test="version != null">#{version},</if> <if test="version != null">#{version},</if>
<if test="ip != null">#{ip},</if> <if test="ip != null">#{ip},</if>
<if test="manufacture != null">#{manufacture},</if> <if test="equManuId != null">#{equManuId},</if>
<if test="location != null">#{location},</if> <if test="location != null">#{location},</if>
<if test="equType != null">#{equType},</if> <if test="equTypeId != null">#{equTypeId},</if>
<if test="inCharge != null">#{inCharge},</if> <if test="inCharge != null">#{inCharge},</if>
<if test="installDate != null">#{installDate},</if> <if test="installDate != null">#{installDate},</if>
<if test="lifeCycle != null">#{lifeCycle},</if> <if test="lifeCycle != null">#{lifeCycle},</if>
<if test="warranty != null">#{warranty},</if> <if test="warranty != null">#{warranty},</if>
<if test="createBy != null">#{createBy},</if> <if test="createBy != null">#{createBy},</if>
<if test="createDate != null">#{createDate},</if> <if test="createDate != null">#{createDate},</if>
<if test="equNumber != null">#{equNumber},</if>
COALESCE(#{status,jdbcType=INTEGER}, 0), COALESCE(#{status,jdbcType=INTEGER}, 0),
<if test="equImage != null">#{equImage,jdbcType=BLOB},</if> <if test="equImage != null">#{equImage},</if>
COALESCE(#{failureFrequency,jdbcType=BIGINT}, 0), COALESCE(#{failureFrequency,jdbcType=BIGINT}, 0),
COALESCE(#{gatherFrequency,jdbcType=BIGINT}, 0), COALESCE(#{gatherFrequency,jdbcType=BIGINT}, 0),
<if test="deviceLevel != null">#{deviceLevel},</if> <if test="deviceLevel != null">#{deviceLevel},</if>
@ -400,9 +472,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="name != null">name = #{name},</if> <if test="name != null">name = #{name},</if>
<if test="version != null">version = #{version},</if> <if test="version != null">version = #{version},</if>
<if test="ip != null">ip = #{ip},</if> <if test="ip != null">ip = #{ip},</if>
<if test="manufacture != null">manufacture = #{manufacture},</if> <if test="equManuId != null">manufacture = #{equManuId},</if>
<if test="location != null">location = #{location},</if> <if test="location != null">location = #{location},</if>
<if test="equType != null">equ_type = #{equType},</if> <if test="equTypeId != null">equ_type = #{equTypeId},</if>
<if test="inCharge != null">in_charge = #{inCharge},</if> <if test="inCharge != null">in_charge = #{inCharge},</if>
<if test="installDate != null">install_date = #{installDate},</if> <if test="installDate != null">install_date = #{installDate},</if>
<if test="lifeCycle != null">life_cycle = #{lifeCycle},</if> <if test="lifeCycle != null">life_cycle = #{lifeCycle},</if>
@ -411,6 +483,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="deviceLevel != null">device_level = #{deviceLevel},</if> <if test="deviceLevel != null">device_level = #{deviceLevel},</if>
<if test="supplierId != null">supplier_id = #{supplierId},</if> <if test="supplierId != null">supplier_id = #{supplierId},</if>
<if test="equImage != null">equ_image = #{equImage},</if> <if test="equImage != null">equ_image = #{equImage},</if>
<if test="equNumber != null">equ_number = #{equNumber},</if>
</trim> </trim>
where id = #{id} where id = #{id}
</update> </update>

@ -32,10 +32,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<where> <where>
<if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if> <if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if>
<if test="description != null and description != ''"> and description = #{description}</if> <if test="description != null and description != ''"> and description = #{description}</if>
<if test="contactBy != null "> and contact_by = #{contactBy}</if> <if test="contactBy != null "> and contact_by LIKE CONCAT('%', #{contactBy}, '%')</if>
<if test="contactWay != null and contactWay != ''"> and contact_way = #{contactWay}</if> <if test="contactWay != null and contactWay != ''"> and contact_way = #{contactWay}</if>
<if test="createDate != null "> and create_date = #{createDate}</if> <if test="createDate != null "> and create_date = #{createDate}</if>
<if test="status != null "> and status = #{status}</if> <if test="status != null "> and status = #{status}</if>
<if test="createBy != null "> and create_by LIKE CONCAT('%', #{createBy}, '%')</if>
</where> </where>
</select> </select>

@ -30,9 +30,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<where> <where>
<if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if> <if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if>
<if test="description != null and description != ''"> and description = #{description}</if> <if test="description != null and description != ''"> and description = #{description}</if>
<if test="contactBy != null and contactBy != ''"> and contact_by = #{contactBy}</if> <if test="contactBy != null and contactBy != ''"> and contact_by LIKE CONCAT('%', #{contactBy}, '%')</if>
<if test="contactWay != null and contactWay != ''"> and contact_way = #{contactWay}</if> <if test="contactWay != null and contactWay != ''"> and contact_way = #{contactWay}</if>
<if test="status != null "> and status = #{status}</if> <if test="status != null "> and status = #{status}</if>
<if test="createBy != null and createBy != ''"> and create_by LIKE CONCAT('%', #{createBy}, '%')</if>
</where> </where>
</select> </select>
@ -42,27 +43,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select> </select>
<insert id="insertEquSupplier" parameterType="EquSupplier"> <insert id="insertEquSupplier" parameterType="EquSupplier">
insert into equ_supplier INSERT INTO equ_supplier
<trim prefix="(" suffix=")" suffixOverrides=","> (id, name, description, contact_by, contact_way, create_by, create_time, status)
<if test="id != null">id,</if> VALUES
<if test="name != null">name,</if> (#{id}, #{name}, #{description}, #{contactBy}, #{contactWay}, #{createBy}, #{createTime}, #{status})
<if test="description != null">description,</if>
<if test="contactBy != null">contact_by,</if>
<if test="contactWay != null">contact_way,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="status != null">status,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="name != null">#{name},</if>
<if test="description != null">#{description},</if>
<if test="contactBy != null">#{contactBy},</if>
<if test="contactWay != null">#{contactWay},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="status != null">#{status},</if>
</trim>
</insert> </insert>
<update id="updateEquSupplier" parameterType="EquSupplier"> <update id="updateEquSupplier" parameterType="EquSupplier">

@ -33,6 +33,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="description != null and description != ''"> and description = #{description}</if> <if test="description != null and description != ''"> and description = #{description}</if>
<if test="image != null and image != ''"> and image = #{image}</if> <if test="image != null and image != ''"> and image = #{image}</if>
<if test="createDate != null "> and create_date = #{createDate}</if> <if test="createDate != null "> and create_date = #{createDate}</if>
<if test="createBy != null "> and create_by LIKE CONCAT('%', #{createBy}, '%')</if>
</where> </where>
</select> </select>

@ -35,7 +35,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql> </sql>
<sql id="selectEquVlanVoJoinGather"> <sql id="selectEquVlanVoJoinGather">
select vl.id, g.equ_id, equ_gather_id, main_id, ip_address, subnet_mask, create_time, update_by, vlan_id from equ_vlan vl LEFT JOIN equ_gather g ON vl.equ_gather_id = g.id select vl.id, g.equ_id as equId, equ_gather_id, main_id, ip_address, subnet_mask, create_time, update_by, vlan_id from equ_vlan vl LEFT JOIN equ_gather g ON vl.equ_gather_id = g.id
</sql> </sql>
<select id="selectEquVlanList" parameterType="EquVlan" resultMap="EquVlanResult"> <select id="selectEquVlanList" parameterType="EquVlan" resultMap="EquVlanResult">

@ -49,6 +49,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select> </select>
<select id="selectListOne" resultMap="ScheduleRulesResult">
SELECT *
FROM schedule_rules
WHERE status = 1
</select>
<select id="selectScheduleRulesList" parameterType="ScheduleRules" resultMap="ScheduleRulesResult"> <select id="selectScheduleRulesList" parameterType="ScheduleRules" resultMap="ScheduleRulesResult">
<include refid="selectScheduleRulesVo"/> <include refid="selectScheduleRulesVo"/>
<where> <where>

@ -6,6 +6,7 @@
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<title><%= webpackConfig.name %></title> <title><%= webpackConfig.name %></title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]--> <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style> <style>

@ -0,0 +1,58 @@
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
const api = '/device/files/'
// 查询详细
export function getDict() {
return request({
url: '/sys_dict',
method: 'get'
})
}
// 查询列表
export function list(query) {
return request({
url: api + 'list',
method: 'get',
params: query
})
}
// 查询详细
export function getInfo(id) {
return request({
url: api + '/queryById/' + parseStrEmpty(id),
method: 'get'
})
}
// 新增
export function add(data) {
return request({
url: api + 'add',
method: 'post',
data: data
})
}
// 修改
export function update(data) {
return request({
url: api + 'modify',
method: 'put',
data: data
})
}
// 删除
export function del(id) {
return request({
url: api + 'delete' + id,
method: 'delete'
})
}

@ -0,0 +1,52 @@
import request from '@/utils/request'
// 查询字典数据列表
export function listData(query) {
return request({
url: '/system/dict/data/list',
method: 'get',
params: query
})
}
// 查询字典数据详细
export function getData(dictCode) {
return request({
url: '/system/dict/data/' + dictCode,
method: 'get'
})
}
// 根据字典类型查询字典数据信息
export function getDicts(dictType) {
return request({
url: '/system/dict/data/type/' + dictType,
method: 'get'
})
}
// 新增字典数据
export function addData(data) {
return request({
url: '/system/dict/data',
method: 'post',
data: data
})
}
// 修改字典数据
export function updateData(data) {
return request({
url: '/system/dict/data',
method: 'put',
data: data
})
}
// 删除字典数据
export function delData(dictCode) {
return request({
url: '/system/dict/data/' + dictCode,
method: 'delete'
})
}

@ -0,0 +1,60 @@
import request from '@/utils/request'
// 查询字典类型列表
export function listType(query) {
return request({
url: '/system/dict/type/list',
method: 'get',
params: query
})
}
// 查询字典类型详细
export function getType(dictId) {
return request({
url: '/system/dict/type/' + dictId,
method: 'get'
})
}
// 新增字典类型
export function addType(data) {
return request({
url: '/system/dict/type',
method: 'post',
data: data
})
}
// 修改字典类型
export function updateType(data) {
return request({
url: '/system/dict/type',
method: 'put',
data: data
})
}
// 删除字典类型
export function delType(dictId) {
return request({
url: '/system/dict/type/' + dictId,
method: 'delete'
})
}
// 刷新字典缓存
export function refreshCache() {
return request({
url: '/system/dict/type/refreshCache',
method: 'delete'
})
}
// 获取字典选择框列表
export function optionselect() {
return request({
url: '/system/dict/type/optionselect',
method: 'get'
})
}

@ -0,0 +1,49 @@
import request from '@/utils/request'
const api = '/knowledge/'
// 查询详细
export function getDict() {
return request({
url: '/sys_dict',
method: 'get'
})
}
// 查询列表
export function list(query) {
return request({
url: '/knowBase/query',
method: 'get',
params: query
})
}
// 新增
export function add(data) {
return request({
url: '/knowledge/add',
method: 'post',
data: data
})
}
// 修改
export function update(data) {
return request({
url: '/knowBasemodify',
method: 'put',
data: data
})
}
// 删除
export function del(id) {
return request({
url: '/knowBase/delete/' + id,
method: 'delete'
})
}

@ -1,38 +1,20 @@
import request from '@/utils/request' import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi"; const api = '/device/deviceInformation/'
const api = '/equipment/'
// 立即执行 // 立即执行
export function protoCollect() { export function addRule(data) {
return request({ return request({
url: api + 'protoCollect', url: api + 'addRule',
method: 'post'
})
}
// 定时采集规则添加
export function addTimerRule(data) {
return request({
url: api + 'addTimerRule',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 查询规则 // 查询规则
export function queryTimerRule(data) { export function queryRule() {
return request({ return request({
url: api + 'queryTimerRule', url: api + 'queryRule',
method: 'post', method: 'get'
data: data
}) })
} }
// 修改规则
export function modifyTimerRule(data) {
return request({
url: api + 'modifyTimerRule',
method: 'post',
data: data
})
}

@ -1,6 +1,5 @@
import request from '@/utils/request' import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi"; const api = '/device/deviceManu/'
const api = '/equManufacture/'
// 查询详细 // 查询详细
export function getDict() { export function getDict() {
@ -13,7 +12,7 @@ export function getDict() {
// 查询列表 // 查询列表
export function list(query) { export function list(query) {
return request({ return request({
url: api + 'queryByVO', url: api + 'query',
method: 'get', method: 'get',
params: query params: query
}) })
@ -40,7 +39,7 @@ export function update(data) {
// 删除 // 删除
export function del(id) { export function del(id) {
return request({ return request({
url: api + 'delete' + id, url: api + id,
method: 'delete' method: 'delete'
}) })
} }

@ -1,6 +1,5 @@
import request from '@/utils/request' import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi"; const api = '/device/deviceType/'
const api = '/equipmentType/'
// 查询详细 // 查询详细
export function getDict() { export function getDict() {
@ -13,7 +12,7 @@ export function getDict() {
// 查询列表 // 查询列表
export function list(query) { export function list(query) {
return request({ return request({
url: api + 'queryByVO', url: api + 'query',
method: 'get', method: 'get',
params: query params: query
}) })
@ -40,7 +39,7 @@ export function update(data) {
// 删除 // 删除
export function del(id) { export function del(id) {
return request({ return request({
url: api + 'delete' + id, url: api + id,
method: 'delete' method: 'delete'
}) })
} }

@ -14,7 +14,7 @@ export function getDict() {
export function list(query) { export function list(query) {
return request({ return request({
url: api + 'list', url: api + 'list',
method: 'post', method: 'get',
params: query params: query
}) })
} }
@ -48,7 +48,7 @@ export function update(data) {
// 删除 // 删除
export function del(id) { export function del(id) {
return request({ return request({
url: api + 'delete' + id, url: api + id,
method: 'delete' method: 'delete'
}) })
} }

@ -0,0 +1,49 @@
import request from '@/utils/request'
const api = '/device/supplier/'
// 查询详细
export function getDict() {
return request({
url: '/sys_dict',
method: 'get'
})
}
// 查询列表
export function list(query) {
return request({
url: api + 'query',
method: 'get',
params: query
})
}
// 新增
export function add(data) {
return request({
url: api + 'add',
method: 'post',
data: data
})
}
// 修改
export function update(data) {
return request({
url: api + 'edit',
method: 'put',
data: data
})
}
// 删除
export function del(id) {
return request({
url: api + id,
method: 'delete'
})
}

@ -1,11 +1,11 @@
import request from '@/utils/request' import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi"; import { parseStrEmpty } from "@/utils/ruoyi";
const api = '/equipment/' const api = '/device/files/'
// 查询多台设备列表 // 查询多台设备列表
export function list(query) { export function list(query) {
return request({ return request({
url: api + 'queryByVO', url: api + 'list',
method: 'get', method: 'get',
params: query params: query
}) })
@ -14,20 +14,60 @@ export function list(query) {
// 查询单台设备 // 查询单台设备
export function getInfo(id) { export function getInfo(id) {
return request({ return request({
url: api + '/queryById/' + parseStrEmpty(id), url: api + 'latest/' + parseStrEmpty(id),
method: 'get' method: 'get'
}) })
} }
// 查询设备历史预警 // 设备管理基本信息(获取设备指定时间段内的历史监控信息)
export function historyQuery(query) { export function historyQuery(query) {
return request({ return request({
url: '/alarm/historyQuery', url: api + 'history',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 设备历史预警
export function alertmessage(equId) {
return request({
url: '/inMonitoring/alertmessage/' + parseStrEmpty(equId),
method: 'get'
})
}
// 查询interface接口信息
export function systemInterface(equId) {
return request({
url: '/system/interface/' + parseStrEmpty(equId),
method: 'get'
})
}
// 查询Routing路由信息
export function systemRouting(equId) {
return request({
url: '/system/routing/' + parseStrEmpty(equId),
method: 'get'
})
}
// 查询Veneer单板运行信息
export function systemVeneer(equId) {
return request({
url: '/system/veneer/' + parseStrEmpty(equId),
method: 'get'
})
}
// 查询Vlan信息
export function deviceVlan(equId) {
return request({
url: '/device/vlan/ByEquId/' + parseStrEmpty(equId),
method: 'get'
})
}
// 查询接口信息 // 查询接口信息
export function interfaceQuery(query) { export function interfaceQuery(query) {
return request({ return request({

@ -0,0 +1,58 @@
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
const api = '/inMonitoring/alertMessage/'
// 查询详细
export function getDict() {
return request({
url: '/sys_dict',
method: 'get'
})
}
// 查询列表
export function list(query) {
return request({
url: api + 'list',
method: 'get',
params: query
})
}
// 查询详细
export function getInfo(id) {
return request({
url: api + '/queryById/' + parseStrEmpty(id),
method: 'get'
})
}
// 新增
export function add(data) {
return request({
url: api + 'add',
method: 'post',
data: data
})
}
// 修改
export function update(data) {
return request({
url: api + 'editAlertMessage',
method: 'put',
data: data
})
}
// 删除
export function del(id) {
return request({
url: api + id,
method: 'delete'
})
}

@ -0,0 +1,58 @@
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
const api = '/inMonitoring/alertRule/'
// 查询详细
export function byTable() {
return request({
url: api + 'byTable',
method: 'get'
})
}
// 查询列表
export function list(query) {
return request({
url: api + 'list',
method: 'get',
params: query
})
}
// 查询详细
export function getInfo(id) {
return request({
url: api + '/queryById/' + parseStrEmpty(id),
method: 'get'
})
}
// 新增
export function add(data) {
return request({
url: api + 'addRule',
method: 'post',
data: data
})
}
// 修改
export function update(data) {
return request({
url: api + 'editRule',
method: 'put',
data: data
})
}
// 删除
export function del(id) {
return request({
url: api + id,
method: 'delete'
})
}

@ -0,0 +1,92 @@
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
const api = '/device/files/'
// 查询详细
export function getDict() {
return request({
url: '/sys_dict',
method: 'get'
})
}
// 预警信息统
export function statistic(query) {
return request({
url: '/inMonitoring/alertMessage/statistic/list',
method: 'get',
params: query
})
}
// 统计预警信息次数
export function alertMessageTimes(query) {
return request({
url: 'inMonitoring/alertMessage/times',
method: 'get',
params: query
})
}
// 按设备类型分类统计设备信息
export function byEquType() {
return request({
url: 'device/files/byEquType',
method: 'get'
})
}
// 设备运行状态
export function listMonitor(query) {
return request({
url: 'device/files/monitorById',
method: 'get',
params: query
})
}
// 查询详细
export function getInfo(id) {
return request({
url: api + '/queryById/' + parseStrEmpty(id),
method: 'get'
})
}
// 新增
export function add(data) {
return request({
url: api + 'add',
method: 'post',
data: data
})
}
// 修改
export function update(data) {
return request({
url: api + 'modify',
method: 'put',
data: data
})
}
// 删除
export function del(id) {
return request({
url: api + id,
method: 'delete'
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 38 KiB

@ -4,7 +4,7 @@
multiple multiple
:disabled="disabled" :disabled="disabled"
:action="uploadImgUrl" :action="uploadImgUrl"
list-type="picture-card" :list-type="listType"
:on-success="handleUploadSuccess" :on-success="handleUploadSuccess"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:data="data" :data="data"
@ -19,7 +19,8 @@
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:class="{hide: this.fileList.length >= this.limit}" :class="{hide: this.fileList.length >= this.limit}"
> >
<i class="el-icon-plus"></i> <el-button v-if="listType == 'txt'" size="small" type="primary">点击上传</el-button>
<i class="el-icon-plus" v-else></i>
</el-upload> </el-upload>
<!-- 上传提示 --> <!-- 上传提示 -->
@ -57,6 +58,11 @@ export default {
type: String, type: String,
default: "/common/upload" default: "/common/upload"
}, },
// text/picture/picture-card
listType: {
type: String,
default: "picture-card"
},
// //
data: { data: {
type: Object type: Object
@ -64,7 +70,7 @@ export default {
// //
limit: { limit: {
type: Number, type: Number,
default: 5 default: 1
}, },
// (MB) // (MB)
fileSize: { fileSize: {
@ -195,8 +201,9 @@ export default {
}, },
// //
handleUploadSuccess(res, file) { handleUploadSuccess(res, file) {
console.log("%c 🍍: handleUploadSuccess -> res ", "font-size:16px;background-color:#dca159;color:white;", res)
if (res.code === 200) { if (res.code === 200) {
this.uploadList.push({ name: res.fileName, url: res.fileName }) this.uploadList.push({ name: res.fileName, url: res.url })
this.uploadedSuccessfully() this.uploadedSuccessfully()
} else { } else {
this.number-- this.number--
@ -205,6 +212,8 @@ export default {
this.$refs.imageUpload.handleRemove(file) this.$refs.imageUpload.handleRemove(file)
this.uploadedSuccessfully() this.uploadedSuccessfully()
} }
console.log("%c 🇸🇰: handleUploadSuccess -> this.fileList ", "font-size:16px;background-color:#6a826e;color:white;", this.fileList)
}, },
// //
handleDelete(file) { handleDelete(file) {

@ -99,7 +99,7 @@ export const dynamicRoutes = [
permissions: ['inMonitoring:devicesState:edit'], permissions: ['inMonitoring:devicesState:edit'],
children: [ children: [
{ {
path: 'detail/:userId(\\d+)', path: 'detail/:userId',
component: () => import('@/views/inMonitoring/devicesState/detail'), component: () => import('@/views/inMonitoring/devicesState/detail'),
name: 'DevicesStateDetail', name: 'DevicesStateDetail',
meta: { title: '设备详情', activeMenu: '/inMonitoring/devicesState-detail' } meta: { title: '设备详情', activeMenu: '/inMonitoring/devicesState-detail' }

@ -42,6 +42,7 @@ service.interceptors.request.use(config => {
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime() time: new Date().getTime()
} }
console.log("%c 🛑: requestObj ", "font-size:16px;background-color:#4408a2;color:white;", requestObj)
const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小 const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小
const limitSize = 5 * 1024 * 1024 // 限制存放数据5M const limitSize = 5 * 1024 * 1024 // 限制存放数据5M
if (requestSize >= limitSize) { if (requestSize >= limitSize) {

@ -52,16 +52,16 @@ export function resetForm(refName) {
} }
// 添加日期范围 // 添加日期范围
export function addDateRange(params, dateRange, propName) { export function addDateRange(params, dateRange, propNameStart, propNameEnd) {
let search = params let search = params
search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {} search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}
dateRange = Array.isArray(dateRange) ? dateRange : [] dateRange = Array.isArray(dateRange) ? dateRange : []
if (typeof (propName) === 'undefined') { if (typeof (propNameStart) === 'undefined') {
search.params['beginTime'] = dateRange[0] search.params['beginTime'] = dateRange[0]
search.params['endTime'] = dateRange[1] search.params['endTime'] = dateRange[1]
} else { } else {
search.params['begin' + propName] = dateRange[0] search.params[propNameStart] = dateRange[0]
search.params['end' + propName] = dateRange[1] search.params[propNameEnd] = dateRange[1]
} }
return search return search
} }

@ -4,7 +4,7 @@
<el-card class="customer-service"> <el-card class="customer-service">
<!-- 客服头部 --> <!-- 客服头部 -->
<div class="service-header"> <div class="service-header">
<h2>智能客服</h2> <h2>AI智能助手</h2>
<p>您好我是智能助手很高兴为您服务</p> <p>您好我是智能助手很高兴为您服务</p>
</div> </div>
@ -72,7 +72,7 @@ export default {
newMessage: '', newMessage: '',
messages: [ messages: [
{ {
text: '您好!我是智能客服,请问有什么可以帮您?', text: '您好!我是AI智能助手,请问有什么可以帮您?',
sender: 'service', sender: 'service',
time: this.formatTime(new Date()) time: this.formatTime(new Date())
} }

@ -2,79 +2,31 @@
<div class="app-container"> <div class="app-container">
<el-row :gutter="20"> <el-row :gutter="20">
<splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme"> <splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme">
<!--知识库管理-->
<!--用户数据-->
<pane size="84"> <pane size="84">
<el-col> <el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<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="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceInformation:add']">新增</el-button> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceType:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['device:deviceInformation:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:deviceInformation:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['device:deviceInformation:import']">导入</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <!-- <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> -->
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['device:deviceInformation:export']">导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" /> <el-table-column label="序号" align="center" key="id" prop="id"/>
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" /> <el-table-column label="文件名称" align="center" key="title" prop="title" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" /> <el-table-column label="描述" align="center" key="description" prop="description" :show-overflow-tooltip="true" />
<el-table-column label="创建人" align="center" key="createBy" prop="createBy" :show-overflow-tooltip="true" />
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" /> <el-table-column label="创建时间" align="center" prop="createDate" width="160">
<el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
<template slot-scope="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createDate) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.userId !== 1"> <template slot-scope="scope" v-if="scope.row.id !== 1">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceInformation:edit']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceType:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:deviceInformation:remove']">删除</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:deviceType:remove']">删除</el-button>
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['device:deviceInformation:resetPwd', 'device:deviceInformation:edit']">
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="handleResetPwd" icon="el-icon-key" v-hasPermi="['device:deviceInformation:resetPwd']">重置密码</el-dropdown-item>
<el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check" v-hasPermi="['device:deviceInformation:edit']">分配角色</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -85,67 +37,23 @@
</splitpanes> </splitpanes>
</el-row> </el-row>
<el-dialog :title="title" :visible.sync="open" width="760px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="760px" append-to-body :destroy-on-close="true">
<el-form ref="form" :model="form" :rules="rules" label-width="90px"> <el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-row :gutter="20"> <el-row :gutter="20">
<!-- 用户昵称 + 手机号码 -->
<el-col :span="12">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
</el-form-item>
</el-col>
<!-- 邮箱 + 用户名称 -->
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
<el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
</el-form-item>
</el-col>
<!-- 用户密码仅新增+ 用户性别 -->
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
</el-form-item>
</el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="用户性别"> <el-form-item label="文档标题" prop="title">
<el-select v-model="form.sex" placeholder="请选择性别" style="width: 100%"> <el-input v-model="form.title" placeholder="请输入文档标题" maxlength="30" />
<el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24">
<!-- 状态 + 角色 --> <el-form-item label="文档简介" prop="description">
<el-col :span="12"> <el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入文档简介" />
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色">
<el-select v-model="form.roleIds" multiple placeholder="请选择角色" style="width: 100%">
<el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1"></el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- 备注单独一行 -->
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注"> <el-form-item label="上传文件" prop="fileUrl">
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入内容" /> <ImageUpload @input="upImage" :value="form.fileUrl" :fileType="['docx','txt']" listType="txt"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -158,30 +66,11 @@
</span> </span>
</el-dialog> </el-dialog>
<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user" import { list, del, add, update } from "@/api/QandA/knowledge"
import { getToken } from "@/utils/auth" import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
@ -194,6 +83,7 @@ export default {
components: { Treeselect, Splitpanes, Pane }, components: { Treeselect, Splitpanes, Pane },
data() { data() {
return { return {
appBase:process.env.VUE_APP_BASE_API,
// //
loading: true, loading: true,
// //
@ -206,7 +96,7 @@ export default {
showSearch: true, showSearch: true,
// //
total: 0, total: 0,
// //
userList: null, userList: null,
// //
title: "", title: "",
@ -232,15 +122,15 @@ export default {
children: "children", children: "children",
label: "label" label: "label"
}, },
// //
upload: { upload: {
// //
open: false, open: false,
// //
title: "", title: "",
// //
isUploading: false, isUploading: false,
// //
updateSupport: 0, updateSupport: 0,
// //
headers: { Authorization: "Bearer " + getToken() }, headers: { Authorization: "Bearer " + getToken() },
@ -251,50 +141,18 @@ export default {
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
userName: undefined, name: undefined
phonenumber: undefined,
status: undefined,
deptId: undefined
}, },
//
columns: [
{ key: 0, label: '用户编号', visible: true, showInSelector: true },
{ key: 1, label: '用户名称', visible: true, showInSelector: true },
{ key: 2, label: '用户昵称', visible: true, showInSelector: true },
{ key: 3, label: '部门', visible: false, showInSelector: false }, // 👈
{ key: 4, label: '手机号码', visible: true, showInSelector: true },
{ key: 5, label: '状态', visible: true, showInSelector: true },
{ key: 6, label: '创建时间', visible: true, showInSelector: true }
],
// //
rules: { rules: {
userName: [ name: [
{ required: true, message: "用户名称不能为空", trigger: "blur" }, { required: true, message: "类型名称不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' } { min: 2, max: 20, message: '类型名称长度必须介于 2 和 20 之间', trigger: 'blur' }
],
nickName: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
], ],
password: [ image: [
{ required: true, message: "用户密码不能为空", trigger: "blur" }, { required: true, message: "请上传设备图片", trigger: "blur" },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
], ],
email: [
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"]
}
],
phonenumber: [
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}
]
} }
} }
}, },
@ -306,61 +164,23 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询用户列表 */ /** 查询类型列表 */
getList() { getList() {
this.loading = true this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows this.userList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
} }
) )
}, },
// /** */ upImage(fileList){
// getDeptTree() { console.log(fileList)
// deptTreeSelect().then(response => { this.form.fileUrl = fileList
// this.deptOptions = response.data
// this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
// })
// },
//
filterDisabledDept(deptList) {
return deptList.filter(dept => {
if (dept.disabled) {
return false
}
if (dept.children && dept.children.length) {
dept.children = this.filterDisabledDept(dept.children)
}
return true
})
},
//
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
//
handleNodeClick(data) {
this.queryParams.deptId = data.id
this.handleQuery()
},
//
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"
this.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function() {
return changeUserStatus(row.userId, row.status)
}).then(() => {
this.$modal.msgSuccess(text + "成功")
}).catch(function() {
row.status = row.status === "0" ? "1" : "0"
})
}, },
// //
cancel() { cancel() {
@ -370,18 +190,12 @@ export default {
// //
reset() { reset() {
this.form = { this.form = {
userId: undefined, id: undefined,
deptId: undefined, name: undefined,
userName: undefined, description: undefined,
nickName: undefined, createBy: undefined,
password: undefined, image: undefined,
phonenumber: undefined, createDate: undefined
email: undefined,
sex: undefined,
status: "0",
remark: undefined,
postIds: [],
roleIds: []
} }
this.resetForm("form") this.resetForm("form")
}, },
@ -400,85 +214,35 @@ export default {
}, },
// //
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.userId) this.ids = selection.map(item => item.id)
this.single = selection.length != 1 this.single = selection.length != 1
this.multiple = !selection.length this.multiple = !selection.length
}, },
//
handleCommand(command, row) {
switch (command) {
case "handleResetPwd":
this.handleResetPwd(row)
break
case "handleAuthRole":
this.handleAuthRole(row)
break
default:
break
}
},
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
getUser().then(response => { this.open = true
this.postOptions = response.posts
this.roleOptions = response.roles
this.open = true
this.title = "添加用户"
this.form.password = this.initPassword
})
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
const userId = row.userId || this.ids const id = row.id || this.ids
getUser(userId).then(response => {
this.form = response.data
this.postOptions = response.posts
this.roleOptions = response.roles
this.$set(this.form, "postIds", response.postIds)
this.$set(this.form, "roleIds", response.roleIds)
this.open = true this.open = true
this.title = "修改用户" this.title = "修改类型"
this.form.password = "" this.form = {...row, image: row.image}
})
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
}).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value)
})
}).catch(() => {})
},
/** 分配角色操作 */
handleAuthRole: function(row) {
const userId = row.userId
this.$router.push("/system/user-auth/role/" + userId)
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.userId != undefined) { if (this.form.id != undefined) {
updateUser(this.form).then(response => { update(this.form).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
this.open = false this.open = false
this.getList() this.getList()
}) })
} else { } else {
addUser(this.form).then(response => { add(this.form).then(response => {
this.$modal.msgSuccess("新增成功") this.$modal.msgSuccess("新增成功")
this.open = false this.open = false
this.getList() this.getList()
@ -489,9 +253,9 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const userIds = row.userId || this.ids const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除类型编号为"' + Ids + '"的数据项?').then(function() {
return delUser(userIds) return del(Ids)
}).then(() => { }).then(() => {
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")
@ -505,7 +269,7 @@ export default {
}, },
/** 导入按钮操作 */ /** 导入按钮操作 */
handleImport() { handleImport() {
this.upload.title = "用户导入" this.upload.title = "类型导入"
this.upload.open = true this.upload.open = true
}, },
/** 下载模板操作 */ /** 下载模板操作 */

@ -5,50 +5,59 @@
<!--用户数据--> <!--用户数据-->
<pane size="84"> <pane size="84">
<el-col> <el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="auto"> <el-form :model="queryParams" :rules="rules" ref="form" size="small" :inline="true" v-show="showSearch" label-width="auto">
<el-row> <el-row>
<el-form-item> <el-form-item label="开启定时" prop="queryParams">
<el-button type="primary" icon="el-icon-search" @click="handleQuery">立即执行</el-button> <el-radio-group v-model="queryParams.ruleType">
</el-form-item> <el-radio :label="0">间隔采集</el-radio>
</el-row> <el-radio :label="1">固定时间采集</el-radio>
<el-row> <el-radio :label="2">立即采集</el-radio>
<el-form-item label="开启定时" prop="userName">
<el-radio-group v-model="radio">
<el-radio :label="1">间隔采集</el-radio>
<el-radio :label="2">固定时间采集</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row v-show="radio == 1"> <el-row v-show="queryParams.ruleType == 0">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="采集频率" prop="userName"> <el-form-item label="采集频率" prop="frequency">
<el-input-number v-model="num" controls-position="right" @change="handleChange" :min="1"></el-input-number> <el-input-number v-model="queryParams.frequency" controls-position="right" :min="1"></el-input-number>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="采集时间限制"> <el-form-item label="采集时间限制" prop="dateRange">
<el-time-picker <el-date-picker
is-range v-model="queryParams.dateRange"
v-model="dateRange" @change="handleDateRangeChange"
value-format="yyyy-MM-dd hh:mm:ss"
type="daterange"
range-separator="至" range-separator="至"
start-placeholder="开始时间" start-placeholder="开始日期"
end-placeholder="结束时间" end-placeholder="结束日期"
placeholder="选择时间范围"> :picker-options="{ disabledDate: disablePastDate }"
</el-time-picker> >
</el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row v-show="radio == 2"> <el-row v-show="queryParams.ruleType == 1">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="采集时间限制"> <el-form-item label="采集时间限制">
<el-time-picker <el-date-picker
v-model="dateRange" v-model="queryParams.gatherTime"
:disabledDate="disablePastDate"
value-format="yyyy-MM-dd hh:mm:ss"
type="datetime"
:picker-options="{ disabledDate: disablePastDate }"
placeholder="任意时间点"> placeholder="任意时间点">
</el-time-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="submitForm">确认</el-button>
</el-form-item>
</el-row>
</el-form> </el-form>
</el-col> </el-col>
</pane> </pane>
@ -58,8 +67,7 @@
</template> </template>
<script> <script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user" import { queryRule, getUser, addRule, resetUserPwd, changeUserStatus } from "@/api/device/deviceInformation"
import { protoCollect, addTimerRule, queryTimerRule, modifyTimerRule } from "@/api/device/deviceInformation"
import { getToken } from "@/utils/auth" import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
@ -68,7 +76,6 @@ import "splitpanes/dist/splitpanes.css"
export default { export default {
name: "User", name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'],
components: { Treeselect, Splitpanes, Pane }, components: { Treeselect, Splitpanes, Pane },
data() { data() {
return { return {
@ -90,62 +97,18 @@ export default {
userList: null, userList: null,
// //
title: "", title: "",
//
deptOptions: undefined,
//
enabledDeptOptions: undefined,
// //
open: false, open: false,
// //
deptName: undefined,
//
initPassword: undefined,
//
dateRange: [],
//
postOptions: [],
//
roleOptions: [],
//
form: {},
defaultProps: {
children: "children",
label: "label"
},
//
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
updateSupport: 0,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/system/user/importData"
},
//
queryParams: { queryParams: {
pageNum: 1, ruleType: 0,
pageSize: 10, frequency: 1,
userName: undefined, gatherTime: null,
phonenumber: undefined, startTime: null,
status: undefined, endTime: null,
deptId: undefined //
dateRange: [],
}, },
//
columns: [
{ key: 0, label: '用户编号', visible: true, showInSelector: true },
{ key: 1, label: '用户名称', visible: true, showInSelector: true },
{ key: 2, label: '用户昵称', visible: true, showInSelector: true },
{ key: 3, label: '部门', visible: false, showInSelector: false }, // 👈
{ key: 4, label: '手机号码', visible: true, showInSelector: true },
{ key: 5, label: '状态', visible: true, showInSelector: true },
{ key: 6, label: '创建时间', visible: true, showInSelector: true }
],
// //
rules: { rules: {
@ -153,28 +116,9 @@ export default {
{ required: true, message: "用户名称不能为空", trigger: "blur" }, { required: true, message: "用户名称不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' } { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
], ],
nickName: [ dateRange: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" } { required: true, message: "用户昵称不能为空", trigger: "blur" }
], ],
password: [
{ required: true, message: "用户密码不能为空", trigger: "blur" },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
],
email: [
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"]
}
],
phonenumber: [
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}
]
} }
} }
}, },
@ -186,228 +130,44 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询用户列表 */ /** 查询用户列表 */
getList() { getList() {
this.loading = true this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { queryRule().then(response => {
this.userList = response.rows this.queryParams = {...this.queryParams,...response.data}
this.total = response.total
this.loading = false this.loading = false
} }
) )
}, },
// /** */
// getDeptTree() {
// deptTreeSelect().then(response => {
// this.deptOptions = response.data
// this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
// })
// },
//
filterDisabledDept(deptList) {
return deptList.filter(dept => {
if (dept.disabled) {
return false
}
if (dept.children && dept.children.length) {
dept.children = this.filterDisabledDept(dept.children)
}
return true
})
},
//
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
//
handleNodeClick(data) {
this.queryParams.deptId = data.id
this.handleQuery()
},
//
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"
this.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function() {
return changeUserStatus(row.userId, row.status)
}).then(() => {
this.$modal.msgSuccess(text + "成功")
}).catch(function() {
row.status = row.status === "0" ? "1" : "0"
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
userId: undefined,
deptId: undefined,
userName: undefined,
nickName: undefined,
password: undefined,
phonenumber: undefined,
email: undefined,
sex: undefined,
status: "0",
remark: undefined,
postIds: [],
roleIds: []
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.resetForm("queryForm")
this.queryParams.deptId = undefined
this.$refs.tree.setCurrentKey(null)
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.userId)
this.single = selection.length != 1
this.multiple = !selection.length
},
//
handleCommand(command, row) {
switch (command) {
case "handleResetPwd":
this.handleResetPwd(row)
break
case "handleAuthRole":
this.handleAuthRole(row)
break
default:
break
}
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
getUser().then(response => {
this.postOptions = response.posts
this.roleOptions = response.roles
this.open = true
this.title = "添加用户"
this.form.password = this.initPassword
})
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const userId = row.userId || this.ids
getUser(userId).then(response => {
this.form = response.data
this.postOptions = response.posts
this.roleOptions = response.roles
this.$set(this.form, "postIds", response.postIds)
this.$set(this.form, "roleIds", response.roleIds)
this.open = true
this.title = "修改用户"
this.form.password = ""
})
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
}).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value)
})
}).catch(() => {})
},
/** 分配角色操作 */
handleAuthRole: function(row) {
const userId = row.userId
this.$router.push("/system/user-auth/role/" + userId)
},
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.userId != undefined) { addRule(this.queryParams).then(response => {
updateUser(this.form).then(response => { this.$modal.msgSuccess("新增成功")
this.$modal.msgSuccess("修改成功") this.open = false
this.open = false this.getList()
this.getList() })
})
} else {
addUser(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
} }
}) })
}, },
/** 删除按钮操作 */ handleDateRangeChange(value) {
handleDelete(row) { console.log("%c 🐁: handleDateRangeChange -> value ", "font-size:16px;background-color:#dbe986;color:black;", value)
const userIds = row.userId || this.ids this.queryParams.startTime = value[0]
this.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function() { this.queryParams.endTime = value[1]
return delUser(userIds) },
}).then(() => {
this.getList() disablePastDate(time) {
this.$modal.msgSuccess("删除成功") //
}).catch(() => {}) const today = new Date();
}, // 00:00:00
/** 导出按钮操作 */ today.setHours(0, 0, 0, 0);
handleExport() {
this.download('system/user/export', { // 00:00:00
...this.queryParams console.log("%c 🐇: disablePastDate -> time.getTime() < today.getTime() ", "font-size:16px;background-color:#c5c908;color:black;", time.getTime() , today.getTime(), time.getTime() < today.getTime())
}, `user_${new Date().getTime()}.xlsx`) return time.getTime() < today.getTime();
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "用户导入"
this.upload.open = true
},
/** 下载模板操作 */
importTemplate() {
this.download('system/user/importTemplate', {
}, `user_template_${new Date().getTime()}.xlsx`)
},
//
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
},
//
handleFileSuccess(response, file, fileList) {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
this.getList()
},
//
submitFileForm() {
this.$refs.upload.submit()
} }
} }
} }

@ -12,9 +12,6 @@
<el-form-item label="联系人" prop="contactBy"> <el-form-item label="联系人" prop="contactBy">
<el-input v-model="queryParams.contactBy" placeholder="请输入联系人" clearable style="width: 240px" @keyup.enter.native="handleQuery" /> <el-input v-model="queryParams.contactBy" placeholder="请输入联系人" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="联系电话" prop="contactWay">
<el-input v-model="queryParams.contactWay" placeholder="请输入联系电话" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@ -25,7 +22,7 @@
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceManufacturer:add']">新增</el-button> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceManufacturer:add']">新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <!-- <el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:deviceManufacturer:remove']">删除</el-button> <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:deviceManufacturer:remove']">删除</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@ -33,22 +30,31 @@
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['device:deviceManufacturer:export']">导出</el-button> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['device:deviceManufacturer:export']">导出</el-button>
</el-col> </el-col> -->
</el-row> </el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="ID" align="center" key="Id" prop="Id" /> <el-table-column
label="序号"
width="60"
type="index"
></el-table-column>
<el-table-column label="厂商名称" align="center" key="name" prop="name" width="120" /> <el-table-column label="厂商名称" align="center" key="name" prop="name" width="120" />
<el-table-column label="联系人" align="center" key="contactBy" prop="contactBy" width="120" /> <el-table-column label="联系人" align="center" key="contactBy" prop="contactBy" width="120" />
<el-table-column label="联系方式" align="center" key="contactWay" prop="contactWay" width="120" /> <el-table-column label="联系方式" align="center" key="contactWay" prop="contactWay" width="120" />
<el-table-column label="创建人" align="center" key="CreateBy" prop="CreateBy" width="120" /> <el-table-column label="描述" align="center" key="description" prop="description" width="120" />
<el-table-column label="创建人" align="center" key="createBy" prop="createBy" width="120" />
<el-table-column label="创建日期" align="center" prop="CreateDate" width="160"> <el-table-column label="创建日期" align="center" prop="CreateDate" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.CreateDate) }}</span> <span>{{ parseTime(scope.row.createDate) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" key="status" prop="status" width="120" >
<template slot-scope="scope">
<dict-tag :options="dict.type.device_disable" :value="scope.row.status"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态" align="center" key="Status" prop="Status" width="120" />
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceManufacturer:edit']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceManufacturer:edit']">修改</el-button>
@ -68,12 +74,12 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="厂商名称" prop="name"> <el-form-item label="厂商名称" prop="name">
<el-input v-model="form.name" placeholder="请输入用户昵称" maxlength="30" /> <el-input v-model="form.name" placeholder="请输入联系人" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="联系人" prop="contactBy"> <el-form-item label="联系人" prop="contactBy">
<el-input v-model="form.contactBy" placeholder="请输入手机号码" maxlength="30" /> <el-input v-model="form.contactBy" placeholder="请输入联系人" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -81,6 +87,18 @@
<el-input v-model="form.contactWay" placeholder="请输入手机号码" maxlength="11" /> <el-input v-model="form.contactWay" placeholder="请输入手机号码" maxlength="11" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-select v-model="form.status" placeholder="启用状态" clearable>
<el-option v-for="dict in statusSelections" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="描述" prop="description">
<el-input v-model="form.description" placeholder="请输入描述" type="textarea" :rows="3" />
</el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
@ -112,7 +130,7 @@
</template> </template>
<script> <script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user" import { list, del, add, update, resetUserPwd, changeUserStatus } from "@/api/device/deviceManufacturer"
import { getToken } from "@/utils/auth" import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
@ -121,7 +139,7 @@ import "splitpanes/dist/splitpanes.css"
export default { export default {
name: "User", name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'], dicts: ['sys_normal_disable', 'sys_user_sex','device_disable'],
components: { Treeselect, Splitpanes, Pane }, components: { Treeselect, Splitpanes, Pane },
data() { data() {
return { return {
@ -163,6 +181,11 @@ export default {
children: "children", children: "children",
label: "label" label: "label"
}, },
statusSelections: [
{ label: "正常", value: 1 },
{ label: "停用", value: 0 }
],
// //
upload: { upload: {
// //
@ -183,38 +206,28 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
name: undefined, name: undefined,
contactBy: undefined, contactBy: undefined
status: undefined,
deptId: undefined
}, },
// //
rules: { rules: {
name: [ name: [
{ required: true, message: "用户名称不能为空", trigger: "blur" }, { required: true, message: "厂商名称不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' } { min: 2, max: 20, message: '厂商名称长度必须介于 2 和 20 之间', trigger: 'blur' }
],
nickName: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
],
password: [
{ required: true, message: "用户密码不能为空", trigger: "blur" },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
],
email: [
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"]
}
], ],
contactBy: [ contactBy: [
{ required: true, message: "联系人不能为空", trigger: "blur" }
],
contactWay: [
{ required: true, message: "联系方式不能为空", trigger: "blur" },
{ {
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码", message: "请输入正确的手机号码",
trigger: "blur" trigger: "blur"
} }
] ],
status: [
{ required: true, message: "状态不能为空", trigger: "blur" }
],
} }
} }
}, },
@ -226,16 +239,12 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询用户列表 */ /** 查询用户列表 */
getList() { getList() {
this.loading = true this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows this.userList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
@ -275,7 +284,7 @@ export default {
handleStatusChange(row) { handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用" let text = row.status === "0" ? "启用" : "停用"
this.$modal.confirm('确认要"' + text + '""' + row.name + '"用户吗?').then(function() { this.$modal.confirm('确认要"' + text + '""' + row.name + '"用户吗?').then(function() {
return changeUserStatus(row.Id, row.status) return changeUserStatus(row.id, row.status)
}).then(() => { }).then(() => {
this.$modal.msgSuccess(text + "成功") this.$modal.msgSuccess(text + "成功")
}).catch(function() { }).catch(function() {
@ -290,7 +299,7 @@ export default {
// //
reset() { reset() {
this.form = { this.form = {
Id: undefined, id: undefined,
deptId: undefined, deptId: undefined,
name: undefined, name: undefined,
nickName: undefined, nickName: undefined,
@ -298,7 +307,7 @@ export default {
contactBy: undefined, contactBy: undefined,
email: undefined, email: undefined,
sex: undefined, sex: undefined,
status: "0", status: undefined,
remark: undefined, remark: undefined,
postIds: [], postIds: [],
roleIds: [] roleIds: []
@ -314,13 +323,11 @@ export default {
resetQuery() { resetQuery() {
this.dateRange = [] this.dateRange = []
this.resetForm("queryForm") this.resetForm("queryForm")
this.queryParams.deptId = undefined
this.$refs.tree.setCurrentKey(null)
this.handleQuery() this.handleQuery()
}, },
// //
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.Id) this.ids = selection.map(item => item.id)
this.single = selection.length != 1 this.single = selection.length != 1
this.multiple = !selection.length this.multiple = !selection.length
}, },
@ -340,28 +347,15 @@ export default {
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
getUser().then(response => { this.open = true
this.postOptions = response.posts this.title = "添加厂商"
this.roleOptions = response.roles
this.open = true
this.title = "添加用户"
this.form.password = this.initPassword
})
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
const Id = row.Id || this.ids this.form = {...row}
getUser(Id).then(response => { this.open = true
this.form = response.data this.title = "修改厂商"
this.postOptions = response.posts
this.roleOptions = response.roles
this.$set(this.form, "postIds", response.postIds)
this.$set(this.form, "roleIds", response.roleIds)
this.open = true
this.title = "修改用户"
this.form.password = ""
})
}, },
/** 重置密码按钮操作 */ /** 重置密码按钮操作 */
handleResetPwd(row) { handleResetPwd(row) {
@ -377,28 +371,28 @@ export default {
} }
}, },
}).then(({ value }) => { }).then(({ value }) => {
resetUserPwd(row.Id, value).then(response => { resetUserPwd(row.id, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value) this.$modal.msgSuccess("修改成功,新密码是:" + value)
}) })
}).catch(() => {}) }).catch(() => {})
}, },
/** 分配角色操作 */ /** 分配角色操作 */
handleAuthRole: function(row) { handleAuthRole: function(row) {
const Id = row.Id const id = row.id
this.$router.push("/system/user-auth/role/" + Id) this.$router.push("/system/user-auth/role/" + id)
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.Id != undefined) { if (this.form.id != undefined) {
updateUser(this.form).then(response => { update(this.form).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
this.open = false this.open = false
this.getList() this.getList()
}) })
} else { } else {
addUser(this.form).then(response => { add(this.form).then(response => {
this.$modal.msgSuccess("新增成功") this.$modal.msgSuccess("新增成功")
this.open = false this.open = false
this.getList() this.getList()
@ -409,9 +403,9 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const Ids = row.Id || this.ids const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除用户编号为"' + Ids + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除用户编号为"' + Ids + '"的数据项?').then(function() {
return delUser(Ids) return del(Ids)
}).then(() => { }).then(() => {
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")

@ -221,10 +221,6 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询用户列表 */ /** 查询用户列表 */

@ -11,14 +11,6 @@
<el-form-item label="类型名称" prop="name"> <el-form-item label="类型名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入类型名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" /> <el-input v-model="queryParams.name" placeholder="请输入类型名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="类型状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> -->
<el-form-item label="创建时间">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@ -29,21 +21,17 @@
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceType:add']">新增</el-button> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceType:add']">新增</el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:deviceType:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['device:deviceType:import']">导入</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['device:deviceType:export']">导出</el-button>
</el-col>
<!-- <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> --> <!-- <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> -->
</el-row> </el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="类型编号" align="center" key="Id" prop="Id"/> <el-table-column
label="序号"
width="60"
type="index"
></el-table-column>
<el-table-column label="类型编号" align="center" key="id" prop="id"/>
<el-table-column label="设备类型名称" align="center" key="name" prop="name" :show-overflow-tooltip="true" /> <el-table-column label="设备类型名称" align="center" key="name" prop="name" :show-overflow-tooltip="true" />
<el-table-column label="描述" align="center" key="description" prop="description" :show-overflow-tooltip="true" /> <el-table-column label="描述" align="center" key="description" prop="description" :show-overflow-tooltip="true" />
<el-table-column label="图片" align="center" key="image" prop="image" :show-overflow-tooltip="true" > <el-table-column label="图片" align="center" key="image" prop="image" :show-overflow-tooltip="true" >
@ -51,14 +39,14 @@
<ImagePreview :src="scope.row.image"/> <ImagePreview :src="scope.row.image"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建人" align="center" key="CreateBy" prop="CreateBy" :show-overflow-tooltip="true" /> <el-table-column label="创建人" align="center" key="createBy" prop="createBy" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160"> <el-table-column label="创建时间" align="center" prop="createDate" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createDate) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.Id !== 1"> <template slot-scope="scope" v-if="scope.row.id !== 1">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceType:edit']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceType:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:deviceType:remove']">删除</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:deviceType:remove']">删除</el-button>
</template> </template>
@ -71,24 +59,23 @@
</splitpanes> </splitpanes>
</el-row> </el-row>
<el-dialog :title="title" :visible.sync="open" width="760px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="760px" append-to-body :destroy-on-close="true">
<el-form ref="form" :model="form" :rules="rules" label-width="90px"> <el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-row :gutter="20"> <el-row :gutter="20">
<!-- 类型昵称 + 手机号码 -->
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备名称" prop="name"> <el-form-item label="设备名称" prop="name">
<el-input v-model="form.name" placeholder="请输入类型昵称" maxlength="30" /> <el-input v-model="form.name" placeholder="请输入类型昵称" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="24">
<el-form-item label="设备图片" prop="phonenumber"> <el-form-item label="设备图片" prop="image">
<ImageUpload/> <ImageUpload @input="upImage" :value="form.image"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- 备注单独一行 --> <!-- 备注单独一行 -->
<el-col :span="24"> <el-col :span="24">
<el-form-item label="描述"> <el-form-item label="介绍">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入内容" /> <el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入内容" />
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -102,30 +89,11 @@
</span> </span>
</el-dialog> </el-dialog>
<!-- 类型导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的类型数据
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user" import { list, del, add, update } from "@/api/device/deviceType"
import { getToken } from "@/utils/auth" import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
@ -138,6 +106,7 @@ export default {
components: { Treeselect, Splitpanes, Pane }, components: { Treeselect, Splitpanes, Pane },
data() { data() {
return { return {
appBase:process.env.VUE_APP_BASE_API,
// //
loading: true, loading: true,
// //
@ -195,21 +164,8 @@ export default {
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
name: undefined, name: undefined
phonenumber: undefined,
status: undefined,
deptId: undefined
}, },
//
columns: [
{ key: 0, label: '类型编号', visible: true, showInSelector: true },
{ key: 1, label: '类型名称', visible: true, showInSelector: true },
{ key: 2, label: '类型昵称', visible: true, showInSelector: true },
{ key: 3, label: '部门', visible: false, showInSelector: false }, // 👈
{ key: 4, label: '手机号码', visible: true, showInSelector: true },
{ key: 5, label: '状态', visible: true, showInSelector: true },
{ key: 6, label: '创建时间', visible: true, showInSelector: true }
],
// //
rules: { rules: {
@ -217,28 +173,9 @@ export default {
{ required: true, message: "类型名称不能为空", trigger: "blur" }, { required: true, message: "类型名称不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '类型名称长度必须介于 2 和 20 之间', trigger: 'blur' } { min: 2, max: 20, message: '类型名称长度必须介于 2 和 20 之间', trigger: 'blur' }
], ],
name: [ image: [
{ required: true, message: "类型昵称不能为空", trigger: "blur" } { required: true, message: "请上传设备图片", trigger: "blur" },
],
password: [
{ required: true, message: "类型密码不能为空", trigger: "blur" },
{ min: 5, max: 20, message: '类型密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
], ],
email: [
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"]
}
],
phonenumber: [
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}
]
} }
} }
}, },
@ -250,61 +187,21 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询类型列表 */ /** 查询类型列表 */
getList() { getList() {
this.loading = true this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows this.userList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
} }
) )
}, },
// /** */ upImage(fileList){
// getDeptTree() { console.log(fileList)
// deptTreeSelect().then(response => { this.form.image = fileList
// this.deptOptions = response.data
// this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
// })
// },
//
filterDisabledDept(deptList) {
return deptList.filter(dept => {
if (dept.disabled) {
return false
}
if (dept.children && dept.children.length) {
dept.children = this.filterDisabledDept(dept.children)
}
return true
})
},
//
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
//
handleNodeClick(data) {
this.queryParams.deptId = data.id
this.handleQuery()
},
//
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"
this.$modal.confirm('确认要"' + text + '""' + row.name + '"类型吗?').then(function() {
return changeUserStatus(row.Id, row.status)
}).then(() => {
this.$modal.msgSuccess(text + "成功")
}).catch(function() {
row.status = row.status === "0" ? "1" : "0"
})
}, },
// //
cancel() { cancel() {
@ -314,18 +211,12 @@ export default {
// //
reset() { reset() {
this.form = { this.form = {
Id: undefined, id: undefined,
deptId: undefined,
name: undefined,
name: undefined, name: undefined,
password: undefined,
phonenumber: undefined,
email: undefined,
sex: undefined,
status: "0",
description: undefined, description: undefined,
postIds: [], createBy: undefined,
roleIds: [] image: undefined,
createDate: undefined
} }
this.resetForm("form") this.resetForm("form")
}, },
@ -336,93 +227,40 @@ export default {
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.dateRange = []
this.resetForm("queryForm") this.resetForm("queryForm")
this.queryParams.deptId = undefined
this.$refs.tree.setCurrentKey(null)
this.handleQuery() this.handleQuery()
}, },
// //
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.Id) this.ids = selection.map(item => item.id)
this.single = selection.length != 1 this.single = selection.length != 1
this.multiple = !selection.length this.multiple = !selection.length
}, },
//
handleCommand(command, row) {
switch (command) {
case "handleResetPwd":
this.handleResetPwd(row)
break
case "handleAuthRole":
this.handleAuthRole(row)
break
default:
break
}
},
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
getUser().then(response => { this.open = true
this.postOptions = response.posts
this.roleOptions = response.roles
this.open = true
this.title = "添加类型"
this.form.password = this.initPassword
})
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
const Id = row.Id || this.ids const id = row.id || this.ids
getUser(Id).then(response => {
this.form = response.data
this.postOptions = response.posts
this.roleOptions = response.roles
this.$set(this.form, "postIds", response.postIds)
this.$set(this.form, "roleIds", response.roleIds)
this.open = true this.open = true
this.title = "修改类型" this.title = "修改类型"
this.form.password = "" this.form = {...row, image: row.image}
})
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.name + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "类型密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
}).then(({ value }) => {
resetUserPwd(row.Id, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value)
})
}).catch(() => {})
},
/** 分配角色操作 */
handleAuthRole: function(row) {
const Id = row.Id
this.$router.push("/system/user-auth/role/" + Id)
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.Id != undefined) { if (this.form.id != undefined) {
updateUser(this.form).then(response => { update(this.form).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
this.open = false this.open = false
this.getList() this.getList()
}) })
} else { } else {
addUser(this.form).then(response => { add(this.form).then(response => {
this.$modal.msgSuccess("新增成功") this.$modal.msgSuccess("新增成功")
this.open = false this.open = false
this.getList() this.getList()
@ -433,9 +271,9 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const Ids = row.Id || this.ids const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除类型编号为"' + Ids + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除类型编号为"' + Ids + '"的数据项?').then(function() {
return delUser(Ids) return del(Ids)
}).then(() => { }).then(() => {
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")

@ -6,27 +6,19 @@
<pane size="84"> <pane size="84">
<el-col> <el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="设备名称" prop="Name">
<el-input v-model="queryParams.Name" placeholder="请输入设备名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="安装位置" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入安装位置" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="设备类型" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入设备类型" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="安装日期"> <el-form-item label="安装日期">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker> <el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd hh:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item label="设备名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入设备名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="启用状态" clearable style="width: 240px"> <el-select v-model="queryParams.status" placeholder="启用状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" /> <el-option v-for="dict in dict.type.device_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="设备级别" prop="status"> <el-form-item label="安装位置" prop="location">
<el-select v-model="queryParams.status" placeholder="设备级别" clearable style="width: 240px"> <el-input v-model="queryParams.phonenumber" placeholder="请输入安装位置" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@ -41,53 +33,55 @@
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:files:remove']">删除</el-button> <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:files:remove']">删除</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <!-- <el-col :span="1.5">
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['device:files:import']">导入</el-button> <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['device:files:import']">导入</el-button>
</el-col> </el-col> -->
</el-row> </el-row>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="设备编号" align="center" key="Id" prop="Id" /> <el-table-column
<el-table-column label="设备名称" align="center" key="Name" prop="Name" :show-overflow-tooltip="true" /> label="序号"
<el-table-column label="设备版本" align="center" key="Version" prop="Version" :show-overflow-tooltip="true" /> width="60"
<el-table-column label="设备类型" align="center" key="EquType" prop="EquType" :show-overflow-tooltip="true" /> type="index"
<el-table-column label="设备级别" align="center" prop="phonenumber" width="120" /> ></el-table-column>
<el-table-column label="设备ID" align="center" key="equNumber" prop="equNumber" />
<el-table-column label="设备名称" align="center" key="name" prop="name" :show-overflow-tooltip="true" />
<el-table-column label="设备版本" align="center" key="version" prop="version" :show-overflow-tooltip="true" />
<el-table-column label="设备类型" align="center" key="equType" prop="equType" :show-overflow-tooltip="true" />
<el-table-column label="设备级别" align="center" key="deviceLevel" prop="deviceLevel" width="120" />
<el-table-column label="启用状态" align="center" key="status"> <el-table-column label="启用状态" align="center" key="status">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch> <dict-tag :options="dict.type.device_disable" :value="scope.row.status"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="带外管理IP" align="center" key="Ip" prop="Ip" width="120" /> <el-table-column label="带外管理IP" align="center" key="ip" prop="ip" width="120" />
<el-table-column label="安装位置" align="center" key="location" prop="Location" width="120" />
<el-table-column label="设备厂商" align="center" key="Manufacture" prop="Manufacture" width="120" /> <el-table-column label="安装时间" align="center" prop="installDate" width="160">
<el-table-column label="安装位置" align="center" key="Location" prop="Location" width="120" />
<el-table-column label="安装时间" align="center" prop="InstallDate" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.InstallDate) }}</span> <span>{{ parseTime(scope.row.installDate) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备管理员" align="center" prop="phonenumber" width="120" />
<el-table-column label="预计年限" align="center" key="LifeCycle" prop="LifeCycle" width="120" /> <el-table-column label="设备厂商" align="center" key="manufacture" prop="manufacture" width="120" />
<el-table-column label="服役年限" align="center" key="ServiceTime" prop="ServiceTime" width="120" /> <el-table-column label="设备供应商" align="center" key="supplierName" prop="supplierName" width="120" />
<el-table-column label="设备管理员" align="center" key="inCharge" prop="inCharge" width="120" />
<el-table-column label="预计年限" align="center" key="lifeCycle" prop="lifeCycle" width="120" />
<el-table-column label="服役年限" align="center" key="serviceTime" prop="serviceTime" width="120" />
<el-table-column label="质保时间" align="center" key="warranty" prop="warranty" width="120" /> <el-table-column label="质保时间" align="center" key="warranty" prop="warranty" width="120" />
<el-table-column label="累计预警次数" align="center" key="FailureFrequency" prop="FailureFrequency" width="120" /> <el-table-column label="设备图片" align="center" key="image" prop="image" :show-overflow-tooltip="true" >
<el-table-column label="累计维修次数" align="center" key="RepairFrequency" prop="RepairFrequency" width="120" />
<el-table-column label="累计维修金额" align="center" key="RepairCost" prop="RepairCost" width="120" />
<el-table-column label="设备添加人" align="center" key="CreateBy" prop="CreateBy" width="120" />
<el-table-column label="添加时间" align="center" prop="CreateDate" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <ImagePreview :src="scope.row.image"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="修改人" align="center" prop="UpdateBy" width="120" /> <el-table-column label="设备添加人" align="center" key="createBy" prop="createBy" width="120" />
<el-table-column label="修改时间" align="center" prop="createTime" width="160"> <el-table-column label="添加日期" align="center" prop="createDate" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createDate) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.Id !== 1"> <template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:files:edit']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:files:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:files:remove']">删除</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:files:remove']">删除</el-button>
</template> </template>
@ -104,70 +98,71 @@
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> <el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备编号" prop="nickName"> <el-form-item label="设备编号" prop="equNumber">
<el-input v-model="form.nickName" placeholder="请输入设备编号" maxlength="30" /> <el-input v-model="form.equNumber" placeholder="请输入设备名称" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备名称" prop="nickName"> <el-form-item label="设备名称" prop="name">
<el-input v-model="form.nickName" placeholder="请输入设备名称" maxlength="30" /> <el-input v-model="form.name" placeholder="请输入设备名称" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备版本" prop="nickName"> <el-form-item label="设备版本" prop="version">
<el-input v-model="form.nickName" placeholder="请输入设备版本" maxlength="30" /> <el-input v-model="form.version" placeholder="请输入设备版本" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备类型" prop="nickName"> <el-form-item label="设备类型" prop="equType">
<el-input v-model="form.nickName" placeholder="请输入设备类型" maxlength="30" /> <el-input v-model="form.equType" placeholder="请输入设备类型" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备级别" prop="nickName"> <el-form-item label="设备级别" prop="deviceLevel">
<el-input v-model="form.nickName" placeholder="请输入设备级别" maxlength="30" /> <el-select v-model="form.deviceLevel" placeholder="设备级别" clearable style="width: 240px">
<el-option v-for="dict in dict.type.warning_level" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="带外管理IP" prop="nickName"> <el-form-item label="带外管理IP" prop="ip">
<el-input v-model="form.nickName" placeholder="请输入带外管理IP" maxlength="30" /> <el-input v-model="form.ip" placeholder="请输入带外管理IP" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备厂商" prop="nickName"> <el-form-item label="设备厂商" prop="manufacture">
<el-input v-model="form.nickName" placeholder="请输入设备厂商" maxlength="30" /> <el-input v-model="form.manufacture" placeholder="请输入设备厂商" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="安装位置" prop="nickName"> <el-form-item label="安装位置" prop="location">
<el-input v-model="form.nickName" placeholder="请输入安装位置" maxlength="30" /> <el-input v-model="form.location" placeholder="请输入安装位置" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备管理员" prop="nickName"> <el-form-item label="设备管理员" prop="inCharge">
<el-input v-model="form.nickName" placeholder="请输入设备管理员" maxlength="30" /> <el-input v-model="form.inCharge" placeholder="请输入设备管理员" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="预计年限" prop="nickName"> <el-form-item label="预计年限" prop="lifeCycle">
<el-input v-model="form.nickName" placeholder="请输入预计年限" maxlength="30" /> <el-input v-model="form.lifeCycle" placeholder="请输入预计年限" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="服役年限" prop="nickName"> <el-form-item label="服役年限" prop="serviceTime">
<el-input v-model="form.nickName" placeholder="请输入服役年限" maxlength="30" /> <el-input v-model="form.serviceTime" placeholder="请输入服役年限" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="质保年限" prop="nickName"> <el-form-item label="质保年限" prop="warranty">
<el-input v-model="form.nickName" placeholder="请输入质保年限" maxlength="30" /> <el-input v-model="form.warranty" placeholder="请输入质保年限" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- 备注单独一行 -->
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注"> <el-form-item label="设备图片" prop="image">
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入内容" /> <ImageUpload @input="upImage" :value="form.image"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -212,7 +207,7 @@ import "splitpanes/dist/splitpanes.css"
export default { export default {
name: "User", name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'], dicts: ['device_disable', 'sys_user_sex', 'warning_level'],
components: { Treeselect, Splitpanes, Pane }, components: { Treeselect, Splitpanes, Pane },
data() { data() {
return { return {
@ -273,31 +268,50 @@ export default {
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
Name: undefined, name: undefined,
phonenumber: undefined, status: undefined
status: undefined,
deptId: undefined
}, },
//
columns: [
{ key: 0, label: '设备编号', visible: true, showInSelector: true },
{ key: 1, label: '设备名称', visible: true, showInSelector: true },
{ key: 2, label: '设备级别', visible: true, showInSelector: true },
{ key: 3, label: '部门', visible: false, showInSelector: false }, // 👈
{ key: 4, label: '手机号码', visible: true, showInSelector: true },
{ key: 5, label: '状态', visible: true, showInSelector: true },
{ key: 6, label: '创建时间', visible: true, showInSelector: true }
],
// //
rules: { rules: {
Name: [ equNumber: [
{ required: true, message: "设备名称不能为空", trigger: "blur" }, { required: true, message: "设备编号不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '设备名称长度必须介于 2 和 20 之间', trigger: 'blur' } ],
name: [
{ required: true, message: "设备名称不能为空", trigger: "blur" }
],
version: [
{ required: true, message: "设备版本不能为空", trigger: "blur" },
],
equType: [
{ required: true, message: "设备类型不能为空", trigger: "blur" }
],
deviceLevel: [
{ required: true, message: "设备级别不能为空", trigger: "blur" },
],
ip: [
{ required: true, message: "带外管理IP不能为空", trigger: "blur" }
],
manufacture: [
{ required: true, message: "设备厂商不能为空", trigger: "blur" },
],
location: [
{ required: true, message: "安装位置不能为空", trigger: "blur" }
],
inCharge: [
{ required: true, message: "设备管理员不能为空", trigger: "blur" },
],
lifeCycle: [
{ required: true, message: "预计年限不能为空", trigger: "blur" }
],
serviceTime: [
{ required: true, message: "服役年限不能为空", trigger: "blur" },
],
warranty: [
{ required: true, message: "质保年限不能为空", trigger: "blur" }
],
image: [
{ required: true, message: "设备图片不能为空", trigger: "blur" }
], ],
nickName: [
{ required: true, message: "设备昵称不能为空", trigger: "blur" }
]
} }
} }
}, },
@ -309,68 +323,21 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询设备列表 */
getDicts() {
getDict().then(response => {
console.log("%c 🗝: getDict -> response ", "font-size:16px;background-color:#796b0d;color:white;", response)
}
)
},
/** 查询设备列表 */ /** 查询设备列表 */
getList() { getList() {
this.loading = true this.loading = true
list(this.addDateRange(this.queryParams, this.dateRange)).then(response => { list({minTime:this.dateRange[0],maxTime:this.dateRange[1],...this.queryParams}).then(response => {
this.dataList = response.rows this.dataList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
} }
) )
}, },
// /** */ upImage(fileList){
// getDeptTree() { console.log(fileList)
// deptTreeSelect().then(response => { this.form.image = fileList
// this.deptOptions = response.data
// this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
// })
// },
//
filterDisabledDept(deptList) {
return deptList.filter(dept => {
if (dept.disabled) {
return false
}
if (dept.children && dept.children.length) {
dept.children = this.filterDisabledDept(dept.children)
}
return true
})
},
//
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
//
handleNodeClick(data) {
this.queryParams.deptId = data.id
this.handleQuery()
},
//
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"
this.$modal.confirm('确认要"' + text + '""' + row.Name + '"设备吗?').then(function() {
return changeUserStatus(row.Id, row.status)
}).then(() => {
this.$modal.msgSuccess(text + "成功")
}).catch(function() {
row.status = row.status === "0" ? "1" : "0"
})
}, },
// //
cancel() { cancel() {
@ -380,9 +347,9 @@ export default {
// //
reset() { reset() {
this.form = { this.form = {
Id: undefined, id: undefined,
deptId: undefined, deptId: undefined,
Name: undefined, name: undefined,
nickName: undefined, nickName: undefined,
password: undefined, password: undefined,
phonenumber: undefined, phonenumber: undefined,
@ -403,67 +370,33 @@ export default {
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.dateRange = [] this.dateRange = []
// this.resetForm("queryForm") this.resetForm("queryForm")
// this.queryParams.deptId = undefined this.handleQuery()
// this.$refs.tree.setCurrentKey(null)
// this.handleQuery()
this.getDicts()
}, },
// //
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.Id) this.ids = selection.map(item => item.id)
this.single = selection.length != 1 this.single = selection.length != 1
this.multiple = !selection.length this.multiple = !selection.length
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
// getInfo().then(response => {
// this.postOptions = response.posts
// this.roleOptions = response.roles
// })
this.open = true this.open = true
this.title = "添加设备" this.title = "添加设备"
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
const Id = row.Id || this.ids this.form = {...row}
getInfo(Id).then(response => { this.open = true
this.form = response.data this.title = "修改"
this.postOptions = response.posts
this.roleOptions = response.roles
this.$set(this.form, "postIds", response.postIds)
this.$set(this.form, "roleIds", response.roleIds)
this.open = true
this.title = "修改设备"
this.form.password = ""
})
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.Name + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "设备密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
}).then(({ value }) => {
resetUserPwd(row.Id, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value)
})
}).catch(() => {})
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.Id != undefined) { if (this.form.id != undefined) {
update(this.form).then(response => { update(this.form).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
this.open = false this.open = false
@ -481,20 +414,14 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const Ids = row.Id || this.ids const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除设备编号为"' + Ids + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除设备ID为"' + Ids + '"的数据项?').then(function() {
return del(Ids) return del(Ids)
}).then(() => { }).then(() => {
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")
}).catch(() => {}) }).catch(() => {})
}, },
/** 导出按钮操作 */
handleExport() {
this.download('system/user/export', {
...this.queryParams
}, `user_${new Date().getTime()}.xlsx`)
},
/** 导入按钮操作 */ /** 导入按钮操作 */
handleImport() { handleImport() {
this.upload.title = "设备导入" this.upload.title = "设备导入"

@ -0,0 +1,348 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme">
<!--类型类型管理-->
<pane size="84">
<el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="类型名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入类型名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceType:add']">新增</el-button>
</el-col>
<!-- <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> -->
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column
label="序号"
width="60"
type="index"
></el-table-column>
<el-table-column label="供应商名称" align="center" key="name" prop="name" width="160" :show-overflow-tooltip="true" />
<el-table-column label="联系人" align="center" key="contactBy" prop="contactBy" width="120" />
<el-table-column label="联系方式" align="center" key="contactWay" prop="contactWay" width="120" />
<el-table-column label="描述" align="center" key="description" prop="description" width="120" />
<el-table-column label="创建人" align="center" key="createBy" prop="createBy" width="120" />
<el-table-column label="创建日期" align="center" prop="createTime" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" key="status" prop="status" width="120" >
<template slot-scope="scope">
<span>{{ scope.row.status ? '正常' : '停用' }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.id !== 1">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceType:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:deviceType:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
</el-col>
</pane>
</splitpanes>
</el-row>
<el-dialog :title="title" :visible.sync="open" width="760px" append-to-body :destroy-on-close="true">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="供应商名称" prop="name">
<el-input v-model="form.name" placeholder="请输入联系人" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人" prop="contactBy">
<el-input v-model="form.contactBy" placeholder="请输入联系人" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系方式" prop="contactWay">
<el-input v-model="form.contactWay" placeholder="请输入手机号码" maxlength="11" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-select v-model="form.status" placeholder="启用状态" clearable>
<el-option v-for="dict in statusSelections" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="描述" prop="description">
<el-input v-model="form.description" placeholder="请输入描述" type="textarea" :rows="3" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { list, del, add, update } from "@/api/device/supplier"
import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
export default {
name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'],
components: { Treeselect, Splitpanes, Pane },
data() {
return {
appBase:process.env.VUE_APP_BASE_API,
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
userList: null,
//
title: "",
//
deptOptions: undefined,
//
enabledDeptOptions: undefined,
//
open: false,
//
deptName: undefined,
//
initPassword: undefined,
//
dateRange: [],
//
postOptions: [],
//
roleOptions: [],
//
form: {},
statusSelections: [
{ label: "正常", value: 1 },
{ label: "停用", value: 0 }
],
defaultProps: {
children: "children",
label: "label"
},
//
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
updateSupport: 0,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/system/user/importData"
},
//
queryParams: {
pageNum: 1,
pageSize: 10,
name: undefined
},
//
rules: {
name: [
{ required: true, message: "供应商名称不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '供应商名称长度必须介于 2 和 20 之间', trigger: 'blur' }
],
contactBy: [
{ required: true, message: "联系人不能为空", trigger: "blur" }
],
contactWay: [
{ required: true, message: "联系方式不能为空", trigger: "blur" },
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}
],
status: [
{ required: true, message: "状态不能为空", trigger: "blur" }
],
}
}
},
watch: {
//
deptName(val) {
this.$refs.tree.filter(val)
}
},
created() {
this.getList()
},
methods: {
/** 查询类型列表 */
getList() {
this.loading = true
list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows
this.total = response.total
this.loading = false
}
)
},
upImage(fileList){
console.log(fileList)
this.form.image = fileList
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
id: undefined,
name: undefined,
description: undefined,
createBy: undefined,
image: undefined,
createDate: undefined
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.resetForm("queryForm")
this.queryParams.deptId = undefined
this.$refs.tree.setCurrentKey(null)
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length != 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
this.open = true
this.title = "修改类型"
this.form = {...row, image: row.image}
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != undefined) {
update(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
add(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除类型编号为"' + Ids + '"的数据项?').then(function() {
return del(Ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => {})
},
/** 导出按钮操作 */
handleExport() {
this.download('system/user/export', {
...this.queryParams
}, `user_${new Date().getTime()}.xlsx`)
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "类型导入"
this.upload.open = true
},
/** 下载模板操作 */
importTemplate() {
this.download('system/user/importTemplate', {
}, `user_template_${new Date().getTime()}.xlsx`)
},
//
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
},
//
handleFileSuccess(response, file, fileList) {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
this.getList()
},
//
submitFileForm() {
this.$refs.upload.submit()
}
}
}
</script>

@ -306,10 +306,6 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询用户列表 */ /** 查询用户列表 */

@ -1,75 +1,485 @@
<template> <template>
<div class=""> <div class="body" @click="handleDetail(cardData)">
<h3 class="h3" @click="handleDetail">交换机</h3> <div class="dashboard">
<el-row> <!-- 上层左侧图片右侧参数 -->
<el-col :span="14"> <div class="top-section">
<img src="../../../assets/images/profile.jpg" width="100%" alt="" srcset=""> <!-- 左侧图片 -->
</el-col> <div class="card">
<el-col :span="9" offset="1"> <div class="card-header">
<p> <h2 class="card-title">
<span>在线状态:</span><br/> <i class="fas fa-network-wired"></i>
<span>在线</span> {{cardData.name}}
</p> </h2>
<p> <span class="status-badge status-online">
<span>设备级别:</span><br/> <i class="fas fa-circle"></i> 在线
<span>A</span> </span>
</p> </div>
<p>
<span>安装位置:</span><br/> <div class="device-box">
<span>在线</span> <div class="device-image">
</p> <i class="fas fa-server"></i>
<p> </div>
<span>品牌型号:</span><br/> <div class="device-info">
<span>在线</span> <div class="info-item">
</p> <span class="info-label">
</el-col> <i class="fas fa-layer-group"></i> 设备级别
</el-row> </span>
<el-divider></el-divider> <span class="info-value">A级</span>
</div>
<el-row> <div class="info-item">
<el-col :span="7"> <span class="info-label">
<BarChart2 height="100px"></BarChart2> <i class="fas fa-map-marker-alt"></i> 安装位置
</el-col> </span>
<el-col :span="7"> <span class="info-value">一层</span>
<BarChart height="100px"></BarChart> </div>
</el-col> <div class="info-item">
<el-col :span="10"> <span class="info-label">
<el-button round type="danger" size="mini">危险</el-button> <i class="fas fa-tag"></i> 品牌型号
</span>
<p> <span class="info-value">Cisco</span>
<span>待处理预警数:</span> </div>
<span>待开发</span> <div class="info-item">
</p> <span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态
<p> </span>
<span>预警总数:</span> <span class="info-value">运行正常</span>
<span>待开发</span> </div>
</p> </div>
</el-col> </div>
</el-row>
<div class="metrics-grid">
<div class="metric-card">
<div class="metric-value cpu-usage">66%</div>
<div class="metric-label">CPU占用</div>
<div class="progress-bar">
<div class="progress-fill" style="width: 66%"></div>
</div>
</div>
<div class="metric-card">
<div class="metric-value cpu-usage">66%</div>
<div class="metric-label">内存占用</div>
<div class="progress-bar">
<div class="progress-fill" style="width: 66%"></div>
</div>
</div>
<div class="metric-card">
<div class="metric-value alert-pending">待开发</div>
<div class="metric-label">待处理预警数</div>
</div>
<div class="metric-card">
<div class="metric-value alert-total">待开发</div>
<div class="metric-label">预警总数</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import * as echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import BarChart from './BarChart1.vue' import BarChart from './BarChart1.vue'
import BarChart2 from './BarChart2.vue' import BarChart2 from './BarChart2.vue'
export default { export default {
name: "cardItem", name: "cardItem",
components: { BarChart, BarChart2 }, components: { BarChart, BarChart2 },
props: {
cardData: {
type: Object,
default: () => ({})
}
},
data() { data() {
return { return {
} }
}, },
created() { mounted() {
// this.initCharts();
}, },
methods: { methods: {
initCharts() {
//
const performanceChart = echarts.init(document.getElementById('performanceChart'));
performanceChart.setOption({
tooltip: {
trigger: 'axis'
},
legend: {
data: ['CPU使用率', '内存使用率'],
textStyle: {
color: '#718096'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00', '24:00'],
axisLine: {
lineStyle: {
color: '#cbd5e0'
}
},
axisLabel: {
color: '#718096'
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#cbd5e0'
}
},
axisLabel: {
color: '#718096',
formatter: '{value}%'
},
splitLine: {
lineStyle: {
color: 'rgba(203, 213, 224, 0.6)'
}
}
},
series: [
{
name: 'CPU使用率',
type: 'line',
smooth: true,
data: [45, 52, 38, 66, 58, 62, 48],
lineStyle: {
color: '#ed8936'
},
itemStyle: {
color: '#ed8936'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(237, 137, 54, 0.3)'
}, {
offset: 1, color: 'rgba(237, 137, 54, 0.1)'
}]
}
}
},
{
name: '内存使用率',
type: 'line',
smooth: true,
data: [30, 45, 35, 50, 42, 38, 32],
lineStyle: {
color: '#4299e1'
},
itemStyle: {
color: '#4299e1'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(66, 153, 225, 0.3)'
}, {
offset: 1, color: 'rgba(66, 153, 225, 0.1)'
}]
}
}
}
]
});
//
window.addEventListener('resize', function() {
performanceChart.resize();
trafficChart.resize();
});
},
/** 查看详情 */ /** 查看详情 */
handleDetail: function(row) { handleDetail: function(row) {
console.log("%c 🖍: row ", "font-size:16px;background-color:#3c235b;color:white;", row) console.log("%c 🐋: row ", "font-size:16px;background-color:#46dc4d;color:black;", row)
const userId = row.pointerId const userId = row.id
this.$router.push("/inMonitoring/devicesState-detail/detail/" + userId) this.$router.push("/inMonitoring/devicesState-detail/detail/" + userId)
}, },
} }
} }
</script> </script>
<style lang="scss" scoped>
.body {
color: #2d3748;
line-height: 1.6;
min-height: 100vh;
}
.dashboard {
max-width: 1400px;
margin: 0 auto;
}
.header {
text-align: center;
margin-bottom: 40px;
padding: 25px;
border-radius: 20px;
}
.header h1 {
color: #2d3748;
margin-bottom: 10px;
font-size: 36px;
font-weight: 700;
background: linear-gradient(90deg, #4299e1, #38b2ac);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.header p {
color: #718096;
font-size: 18px;
}
.top-section {
display: grid;
// grid-template-columns: 1fr 2fr;
gap: 30px;
}
.bottom-section {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 30px;
}
.card {
background: rgba(255, 255, 255, 0.9);
border-radius: 20px;
padding: 10px 30px 30px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.9);
transition: all 0.4s ease;
position: relative;
overflow: hidden;
}
.card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #4299e1, #38b2ac);
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.12);
border-color: rgba(66, 153, 225, 0.3);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 25px;
// padding-bottom: 15px;
border-bottom: 1px solid rgba(226, 232, 240, 0.8);
}
.card-title {
font-size: 22px;
font-weight: 700;
color: #2d3748;
display: flex;
align-items: center;
gap: 12px;
}
.card-title i {
color: #4299e1;
font-size: 24px;
}
.status-badge {
padding: 6px 15px;
border-radius: 20px;
font-size: 13px;
font-weight: 600;
}
.status-online {
background: rgba(72, 187, 120, 0.15);
color: #38a169;
border: 1px solid rgba(72, 187, 120, 0.3);
}
.status-danger {
background: rgba(245, 101, 101, 0.15);
color: #e53e3e;
border: 1px solid rgba(245, 101, 101, 0.3);
}
.device-image {
width: 100%;
height: 280px;
background: linear-gradient(135deg, #edf2f7, #e2e8f0);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
border: 1px solid rgba(226, 232, 240, 0.8);
}
.device-image i {
font-size: 80px;
color: #4299e1;
opacity: 0.8;
}
.device-box {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 15px;
}
.device-info {
display: grid;
grid-template-columns: 1fr;
gap: 15px;
}
.info-item {
display: flex;
flex-direction: column;
padding: 4px 12px;
background: rgba(255, 255, 255, 0.7);
border-radius: 12px;
border: 1px solid rgba(226, 232, 240, 0.8);
transition: all 0.3s ease;
}
.info-item:hover {
background: rgba(255, 255, 255, 0.9);
border-color: rgba(66, 153, 225, 0.3);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.info-label {
font-size: 13px;
color: #718096;
margin-bottom: 6px;
display: flex;
align-items: center;
gap: 6px;
}
.info-label i {
font-size: 12px;
color: #4299e1;
}
.info-value {
font-size: 14px;
font-weight: 600;
color: #2d3748;
}
.chart-container {
width: 100%;
height: 300px;
margin-top: 10px;
}
.metrics-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-top: 20px;
}
.metric-card {
padding: 10px;
background: rgba(255, 255, 255, 0.7);
border-radius: 12px;
border: 1px solid rgba(226, 232, 240, 0.8);
text-align: center;
transition: all 0.3s ease;
}
.metric-card:hover {
background: rgba(255, 255, 255, 0.9);
border-color: rgba(66, 153, 225, 0.3);
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.metric-value {
font-size: 24px;
font-weight: 700;
margin-bottom: 8px;
}
.metric-label {
font-size: 14px;
color: #718096;
}
.cpu-usage {
color: #ed8936;
}
.alert-pending {
color: #e53e3e;
}
.alert-total {
color: #4299e1;
}
.progress-bar {
height: 8px;
background: rgba(226, 232, 240, 0.8);
border-radius: 4px;
overflow: hidden;
margin-top: 10px;
}
.progress-fill {
height: 100%;
border-radius: 4px;
transition: width 0.8s ease;
background: linear-gradient(90deg, #ed8936, #dd6b20);
box-shadow: 0 0 10px rgba(237, 137, 54, 0.3);
}
@media (max-width: 1024px) {
.top-section, .bottom-section {
grid-template-columns: 1fr;
}
}
</style>

@ -1,198 +1,679 @@
<template> <template>
<div class="app-container"> <div class="body">
<el-row :gutter="5"> <div class="dashboard">
<el-col :span="24"> <!-- 上层左侧图片右侧参数 -->
<el-card> <div class="top-section0">
<el-row> <div class="card">
<el-col :span="4"> <div class="card-header">
<h3>交换机</h3> <h2 class="card-title">
</el-col> <i class="fas fa-network-wired"></i>
<el-col :span="4"> 设备概览
<h3>持续在线XXXXX小时</h3> </h2>
</el-col> <span class="status-badge status-online">
</el-row> <i class="fas fa-circle"></i> 在线
<el-divider></el-divider> </span>
</div>
<div class="top-section-con">
<div class="device-image">
<i class="fas fa-server"></i>
</div>
<!-- 设备基本信息 -->
<div class="device-info">
<div class="info-title">设备基本信息</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-layer-group"></i> 设备级别
</span>
<span class="info-value">A级</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置
</span>
<span class="info-value">数据中心-主柜</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-tag"></i> 品牌型号
</span>
<span class="info-value">Cisco</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态
</span>
<span class="info-value">运行正常</span>
</div>
</div>
<el-row> <!-- 设备基本信息 -->
<el-col :span="8"> <div class="device-info">
<h3>交换机</h3> <div class="info-title">设备基本信息</div>
</el-col> <div class="info-item">
<el-col :span="4"> <span class="info-label">
<h3>设备基本信息</h3> <i class="fas fa-layer-group"></i> 设备级别
<p> </span>
<span>设备型号:</span> <span class="info-value">A级</span>
<span>待开发</span> </div>
</p> <div class="info-item">
<p> <span class="info-label">
<span>设备级别:</span> <i class="fas fa-map-marker-alt"></i> 安装位置
<span>待开发</span> </span>
</p> <span class="info-value">数据中心-主柜</span>
<p> </div>
<span>设备版本:</span> <div class="info-item">
<span>待开发</span> <span class="info-label">
</p> <i class="fas fa-tag"></i> 品牌型号
<p> </span>
<span>设备类型:</span> <span class="info-value">Cisco</span>
<span>待开发</span> </div>
</p> <div class="info-item">
</el-col> <span class="info-label">
<el-col :span="4"> <i class="fas fa-heartbeat"></i> 运行状态
<h3>设备出厂信息</h3> </span>
<p> <span class="info-value">运行正常</span>
<span>生产商名称:</span> </div>
<span>待开发</span> </div>
</p>
<p>
<span>供货商名称:</span>
<span>待开发</span>
</p>
<p>
<span>出厂日期:</span>
<span>待开发</span>
</p>
<p>
<span>质保时间:</span>
<span>待开发</span>
</p>
<p>
<span>联系人:</span>
<span>待开发</span>
</p>
<p>
<span>联系电话:</span>
<span>待开发</span>
</p>
</el-col>
<el-col :span="4">
<h3>设备管理信息</h3>
<p>
<span>带外IP管理:</span>
<span>待开发</span>
</p>
<p>
<span>安装位置:</span>
<span>待开发</span>
</p>
<p>
<span>安装日期:</span>
<span>待开发</span>
</p>
<p>
<span>服役年限:</span>
<span>待开发</span>
</p>
<p>
<span>管理员:</span>
<span>待开发</span>
</p>
</el-col>
<el-col :span="4">
<h3>设备状态信息</h3>
<p>
<span>累计预警次数:</span>
<span>待开发</span>
</p>
<p>
<span>累计维修次数:</span>
<span>待开发</span>
</p>
</el-col>
</el-row>
</el-card>
</el-col>
</el-row>
<el-row class="mt10" :gutter="10">
<el-col :span="12">
<el-card :style="{height: '500px'}">
<el-row>
<el-col :span="24" class="flex alignItems gap10">
<h3>设备运行数据</h3>
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-col>
<el-col :span="14">
<el-row>
<el-col :span="12">
<LineChart></LineChart>
</el-col>
<el-col :span="12">
<LineChart></LineChart>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<LineChart></LineChart>
</el-col>
<el-col :span="12">
<LineChart></LineChart>
</el-col>
</el-row>
</el-col>
<el-col :span="10">
<el-row>
<el-col :span="12">
<BarChart height="200px" :dateRange="dateRange"></BarChart>
</el-col>
<el-col :span="12">
<BarChart height="200px" :dateRange="dateRange"></BarChart>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<BarChart2 height="200px" :dateRange="dateRange"></BarChart2>
</el-col>
<el-col :span="8">
<BarChart2 height="200px" :dateRange="dateRange"></BarChart2>
</el-col>
<el-col :span="8">
<BarChart2 height="200px" :dateRange="dateRange"></BarChart2>
</el-col>
</el-row>
</el-col>
</el-row> <!-- 设备基本信息 -->
</el-card> <div class="device-info">
</el-col> <div class="info-title">设备基本信息</div>
<el-col :span="12"> <div class="info-item">
<el-card :style="{height: '500px'}"> <span class="info-label">
<el-tabs v-model="selectedTab"> <i class="fas fa-layer-group"></i> 设备级别
<el-tab-pane label="历史预警" :name="1"> </span>
历史预警 <span class="info-value">A级</span>
</el-tab-pane> </div>
<el-tab-pane label="接口信息" :name="2"> <div class="info-item">
接口信息 <span class="info-label">
</el-tab-pane> <i class="fas fa-map-marker-alt"></i> 安装位置
<el-tab-pane label="其他指标" :name="3"> </span>
其他指标 <span class="info-value">数据中心-主柜</span>
</el-tab-pane> </div>
</el-tabs> <div class="info-item">
</el-card> <span class="info-label">
</el-col> <i class="fas fa-tag"></i> 品牌型号
</el-row> </span>
</div> <span class="info-value">Cisco</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态
</span>
<span class="info-value">运行正常</span>
</div>
</div>
<!-- 设备基本信息 -->
<div class="device-info">
<div class="info-title">设备基本信息</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-layer-group"></i> 设备级别
</span>
<span class="info-value">A级</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置
</span>
<span class="info-value">数据中心-主柜</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-tag"></i> 品牌型号
</span>
<span class="info-value">Cisco</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态
</span>
<span class="info-value">运行正常</span>
</div>
</div>
</div>
</div>
</div>
<!-- 下层图表加参数 -->
<div class="bottom-section">
<!-- 左侧图表 -->
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-chart-bar"></i>
设备运行数据
</h2>
<el-date-picker
v-model="daterange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</div>
<div class="chart-container" id="performanceChart"></div>
<div class="chart-container" id="trafficChart"></div>
</div>
<!-- 右侧参数 -->
<div class="card">
<div class="card-header">
<div class="tab-top">
<div class="top-item" v-for="(i,k) in tabs" :key="k" :class="k == tabIndex ?'ac':''" @click="tabIndex = k">
<span>{{ i.name }}</span>
</div>
</div>
</div>
<div class="metrics-grid">
<div class="bottom-item" v-if="tabIndex == 0">
<History/>
</div>
</div>
</div>
</div>
</div>
</div>
</template> </template>
<script> <script>
import BarChart from './BarChart1.vue' import * as echarts from 'echarts'
import LineChart from './LineChart.vue' require('echarts/theme/macarons') // echarts theme
import BarChart2 from './BarChart2.vue' import History from './history.vue'
export default { export default {
name: "cardItem", name: "cardItem",
components: { BarChart, BarChart2, LineChart }, components: { History },
data() { data() {
return { return {
dateRange: [], dateRange: [],
selectedTab: 1 selectedTab: 1,
tabs: [
{ name: '历史预警' },
{ name: '接口信息' },
{ name: 'VLAN信息' },
{ name: '路由表信息' },
],
tabIndex: 0,
} }
}, },
created() { mounted() {
}, this.initCharts();
},
methods: { methods: {
initCharts() {
//
const performanceChart = echarts.init(document.getElementById('performanceChart'));
performanceChart.setOption({
tooltip: {
trigger: 'axis'
},
legend: {
data: ['CPU使用率', '内存使用率'],
textStyle: {
color: '#718096'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00', '24:00'],
axisLine: {
lineStyle: {
color: '#cbd5e0'
}
},
axisLabel: {
color: '#718096'
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#cbd5e0'
}
},
axisLabel: {
color: '#718096',
formatter: '{value}%'
},
splitLine: {
lineStyle: {
color: 'rgba(203, 213, 224, 0.6)'
}
}
},
series: [
{
name: 'CPU使用率',
type: 'line',
smooth: true,
data: [45, 52, 38, 66, 58, 62, 48],
lineStyle: {
color: '#ed8936'
},
itemStyle: {
color: '#ed8936'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(237, 137, 54, 0.3)'
}, {
offset: 1, color: 'rgba(237, 137, 54, 0.1)'
}]
}
}
},
{
name: '内存使用率',
type: 'line',
smooth: true,
data: [30, 45, 35, 50, 42, 38, 32],
lineStyle: {
color: '#4299e1'
},
itemStyle: {
color: '#4299e1'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(66, 153, 225, 0.3)'
}, {
offset: 1, color: 'rgba(66, 153, 225, 0.1)'
}]
}
}
}
]
});
//
const trafficChart = echarts.init(document.getElementById('trafficChart'));
trafficChart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['入站流量', '出站流量'],
textStyle: {
color: '#718096'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
axisLine: {
lineStyle: {
color: '#cbd5e0'
}
},
axisLabel: {
color: '#718096'
}
},
yAxis: {
type: 'value',
name: 'MB/s',
axisLine: {
lineStyle: {
color: '#cbd5e0'
}
},
axisLabel: {
color: '#718096'
},
splitLine: {
lineStyle: {
color: 'rgba(203, 213, 224, 0.6)'
}
}
},
series: [
{
name: '入站流量',
type: 'bar',
data: [320, 332, 301, 334, 390, 330, 320],
itemStyle: {
color: '#4299e1'
}
},
{
name: '出站流量',
type: 'bar',
data: [220, 182, 191, 234, 290, 330, 310],
itemStyle: {
color: '#ed8936'
}
}
]
});
//
window.addEventListener('resize', function() {
performanceChart.resize();
trafficChart.resize();
});
}
} }
} }
</script> </script>
<style lang="less" scoped> <style scoped>
.body {
background: linear-gradient(135deg, #f8fafc, #e2e8f0);
color: #2d3748;
line-height: 1.6;
padding: 20px;
min-height: 100vh;
}
.dashboard {
max-width: 1400px;
margin: 0 auto;
}
.header {
text-align: center;
margin-bottom: 40px;
padding: 25px;
background: rgba(255, 255, 255, 0.8);
border-radius: 20px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.9);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
}
.header h1 {
color: #2d3748;
margin-bottom: 10px;
font-size: 36px;
font-weight: 700;
background: linear-gradient(90deg, #4299e1, #38b2ac);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.header p {
color: #718096;
font-size: 18px;
}
.top-section0 {
margin-bottom: 20px;
}
.top-section-con {
display: grid;
grid-template-columns: 3fr 1fr 1fr 1fr 1fr;
gap: 30px;
}
.top-section {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 30px;
margin-bottom: 30px;
}
.bottom-section {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.card {
background: rgba(255, 255, 255, 0.9);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.9);
transition: all 0.4s ease;
position: relative;
overflow: hidden;
}
.card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #4299e1, #38b2ac);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 1px solid rgba(226, 232, 240, 0.8);
}
.card-title {
font-size: 18px;
font-weight: 700;
color: #2d3748;
display: flex;
align-items: center;
gap: 12px;
}
.card-title i {
color: #4299e1;
font-size: 24px;
}
.status-badge {
padding: 6px 15px;
border-radius: 20px;
font-size: 13px;
font-weight: 600;
}
.status-online {
background: rgba(72, 187, 120, 0.15);
color: #38a169;
border: 1px solid rgba(72, 187, 120, 0.3);
}
.status-danger {
background: rgba(245, 101, 101, 0.15);
color: #e53e3e;
border: 1px solid rgba(245, 101, 101, 0.3);
}
.device-image {
width: 100%;
height: 400px;
background: linear-gradient(135deg, #edf2f7, #e2e8f0);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
/* margin-bottom: 20px; */
overflow: hidden;
border: 1px solid rgba(226, 232, 240, 0.8);
}
.device-image i {
font-size: 80px;
color: #4299e1;
opacity: 0.8;
}
.device-info {
display: grid;
grid-template-columns: 1fr;
gap: 15px;
}
.info-title {
color: #2d3748;
font-size: 16px;
font-weight: 600;
text-align: center;
}
.info-item {
display: flex;
flex-direction: column;
padding: 12px;
background: rgba(255, 255, 255, 0.7);
border-radius: 12px;
border: 1px solid rgba(226, 232, 240, 0.8);
transition: all 0.3s ease;
}
.info-item:hover {
background: rgba(255, 255, 255, 0.9);
border-color: rgba(66, 153, 225, 0.3);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.info-label {
font-size: 13px;
color: #718096;
margin-bottom: 6px;
display: flex;
align-items: center;
gap: 6px;
}
.info-label i {
font-size: 12px;
color: #4299e1;
}
.info-value {
font-size: 14px;
font-weight: 600;
color: #2d3748;
}
.chart-container {
width: 100%;
height: 300px;
margin-top: 10px;
}
.metrics-grid {
margin-top: 20px;
}
.metric-card {
padding: 20px;
background: rgba(255, 255, 255, 0.7);
border-radius: 12px;
border: 1px solid rgba(226, 232, 240, 0.8);
text-align: center;
transition: all 0.3s ease;
}
.metric-card:hover {
background: rgba(255, 255, 255, 0.9);
border-color: rgba(66, 153, 225, 0.3);
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.metric-value {
font-size: 32px;
font-weight: 700;
margin-bottom: 8px;
}
.metric-label {
font-size: 14px;
color: #718096;
}
.cpu-usage {
color: #ed8936;
}
.alert-pending {
color: #e53e3e;
}
.alert-total {
color: #4299e1;
}
.progress-bar {
height: 8px;
background: rgba(226, 232, 240, 0.8);
border-radius: 4px;
overflow: hidden;
margin-top: 10px;
}
.progress-fill {
height: 100%;
border-radius: 4px;
transition: width 0.8s ease;
background: linear-gradient(90deg, #ed8936, #dd6b20);
box-shadow: 0 0 10px rgba(237, 137, 54, 0.3);
}
@media (max-width: 1024px) {
.top-section, .bottom-section {
grid-template-columns: 1fr;
}
}
</style> .tab-top{
display: flex;
gap: 20px;
}
.top-item{
color: #2d3748;
font-weight: 400;
font-size:18px ;
cursor: pointer;
}
.top-item.ac{
font-weight: 600;
border-bottom: 2px solid #2d3748;
}
</style>

@ -0,0 +1,69 @@
<template>
<div class="">
<el-row :gutter="20">
<el-col>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column
label="序号"
width="60"
type="index"
></el-table-column>
<el-table-column label="预警时间" align="center" key="id" prop="id"/>
<el-table-column label="预警等级" align="center" key="name" prop="name" :show-overflow-tooltip="true" />
<el-table-column label="预警信息" align="center" key="description" prop="description" :show-overflow-tooltip="true" />
<el-table-column label="预警状态" align="center" key="createBy" prop="createBy" :show-overflow-tooltip="true" />
<el-table-column label="处理人" align="center" key="createBy" prop="createBy" :show-overflow-tooltip="true" />
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
</el-col>
</el-row>
</div>
</template>
<script>
import { list, del, add, update } from "@/api/device/deviceType"
import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
export default {
name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'],
components: { Treeselect, Splitpanes, Pane },
data() {
return {
//
loading: true,
//
total: 0,
//
userList: null,
//
queryParams: {
pageNum: 1,
pageSize: 10,
name: undefined
},
}
},
created() {
this.getList()
},
methods: {
/** 查询类型列表 */
getList() {
this.loading = true
list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows
this.total = response.total
this.loading = false
}
)
}
}
}
</script>

@ -36,12 +36,10 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="app-container" v-loading="loading"> <div class="bodyBox" v-loading="loading">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="8" class="card-box" v-for="(i,k) in userList" :key="k" @click="handleDetail(i)"> <el-col :span="8" class="card-box" v-for="(i,k) in userList" :key="k" >
<el-card> <cardItem class="cursor" :cardData="i"/>
<cardItem/>
</el-card>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -148,7 +146,7 @@
</template> </template>
<script> <script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/inMonitoring/devicesState" import { list, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus } from "@/api/inMonitoring/devicesState"
import { getToken } from "@/utils/auth" import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import cardItem from "./cardItem.vue" import cardItem from "./cardItem.vue"
@ -274,16 +272,12 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
}, },
methods: { methods: {
/** 查询设备列表 */ /** 查询设备列表 */
getList() { getList() {
this.loading = true this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows this.userList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
@ -383,11 +377,6 @@ export default {
this.form.password = this.initPassword this.form.password = this.initPassword
}) })
}, },
/** 查看详情 */
handleDetail: function(row) {
const userId = row.userId
this.$router.push("/inMonitoring/devicesState-detail/detail/" + userId)
},
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
@ -486,4 +475,17 @@ export default {
} }
} }
} }
</script> </script>
<style scoped>
.bodyBox{
background: linear-gradient(135deg, #f8fafc, #e2e8f0);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.9);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
padding: 10px;
}
.cursor{
cursor: pointer;
}
</style>

@ -1,509 +0,0 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme">
<!--类型类型管理-->
<pane size="84">
<el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="类型名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入类型名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="类型状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:deviceType:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['device:deviceType:import']">导入</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['device:deviceType:export']">导出</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
<el-table-column label="名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="描述" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="触发条件" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="预警等级" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="预警方式" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="预警消息" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.userId !== 1">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:deviceType:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:deviceType:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
</el-col>
</pane>
</splitpanes>
</el-row>
<el-dialog :title="title" :visible.sync="open" width="760px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-row :gutter="20">
<!-- 类型昵称 + 手机号码 -->
<el-col :span="12">
<el-form-item label="类型昵称" prop="nickName">
<el-input v-model="form.nickName" placeholder="请输入类型昵称" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
</el-form-item>
</el-col>
<!-- 邮箱 + 类型名称 -->
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="类型名称" prop="userName">
<el-input v-model="form.userName" placeholder="请输入类型名称" maxlength="30" />
</el-form-item>
</el-col>
<!-- 类型密码仅新增+ 类型性别 -->
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="类型密码" prop="password">
<el-input v-model="form.password" placeholder="请输入类型密码" type="password" maxlength="20" show-password />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型性别">
<el-select v-model="form.sex" placeholder="请选择性别" style="width: 100%">
<el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<!-- 状态 + 角色 -->
<el-col :span="12">
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色">
<el-select v-model="form.roleIds" multiple placeholder="请选择角色" style="width: 100%">
<el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1"></el-option>
</el-select>
</el-form-item>
</el-col>
<!-- 备注单独一行 -->
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入内容" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</span>
</el-dialog>
<!-- 类型导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的类型数据
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/inMonitoring/earlyWarning"
import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
export default {
name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'],
components: { Treeselect, Splitpanes, Pane },
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
userList: null,
//
title: "",
//
deptOptions: undefined,
//
enabledDeptOptions: undefined,
//
open: false,
//
deptName: undefined,
//
initPassword: undefined,
//
dateRange: [],
//
postOptions: [],
//
roleOptions: [],
//
form: {},
defaultProps: {
children: "children",
label: "label"
},
//
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
updateSupport: 0,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/system/user/importData"
},
//
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
phonenumber: undefined,
status: undefined,
deptId: undefined
},
//
columns: [
{ key: 0, label: '类型编号', visible: true, showInSelector: true },
{ key: 1, label: '类型名称', visible: true, showInSelector: true },
{ key: 2, label: '类型昵称', visible: true, showInSelector: true },
{ key: 3, label: '部门', visible: false, showInSelector: false }, // 👈
{ key: 4, label: '手机号码', visible: true, showInSelector: true },
{ key: 5, label: '状态', visible: true, showInSelector: true },
{ key: 6, label: '创建时间', visible: true, showInSelector: true }
],
//
rules: {
userName: [
{ required: true, message: "类型名称不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '类型名称长度必须介于 2 和 20 之间', trigger: 'blur' }
],
nickName: [
{ required: true, message: "类型昵称不能为空", trigger: "blur" }
],
password: [
{ required: true, message: "类型密码不能为空", trigger: "blur" },
{ min: 5, max: 20, message: '类型密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
],
email: [
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"]
}
],
phonenumber: [
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}
]
}
}
},
watch: {
//
deptName(val) {
this.$refs.tree.filter(val)
}
},
created() {
this.getList()
// this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg
})
},
methods: {
/** 查询类型列表 */
getList() {
this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows
this.total = response.total
this.loading = false
}
)
},
// /** */
// getDeptTree() {
// deptTreeSelect().then(response => {
// this.deptOptions = response.data
// this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
// })
// },
//
filterDisabledDept(deptList) {
return deptList.filter(dept => {
if (dept.disabled) {
return false
}
if (dept.children && dept.children.length) {
dept.children = this.filterDisabledDept(dept.children)
}
return true
})
},
//
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
//
handleNodeClick(data) {
this.queryParams.deptId = data.id
this.handleQuery()
},
//
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"
this.$modal.confirm('确认要"' + text + '""' + row.userName + '"类型吗?').then(function() {
return changeUserStatus(row.userId, row.status)
}).then(() => {
this.$modal.msgSuccess(text + "成功")
}).catch(function() {
row.status = row.status === "0" ? "1" : "0"
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
userId: undefined,
deptId: undefined,
userName: undefined,
nickName: undefined,
password: undefined,
phonenumber: undefined,
email: undefined,
sex: undefined,
status: "0",
remark: undefined,
postIds: [],
roleIds: []
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.resetForm("queryForm")
this.queryParams.deptId = undefined
this.$refs.tree.setCurrentKey(null)
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.userId)
this.single = selection.length != 1
this.multiple = !selection.length
},
//
handleCommand(command, row) {
switch (command) {
case "handleResetPwd":
this.handleResetPwd(row)
break
case "handleAuthRole":
this.handleAuthRole(row)
break
default:
break
}
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
getUser().then(response => {
this.postOptions = response.posts
this.roleOptions = response.roles
this.open = true
this.title = "添加类型"
this.form.password = this.initPassword
})
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const userId = row.userId || this.ids
getUser(userId).then(response => {
this.form = response.data
this.postOptions = response.posts
this.roleOptions = response.roles
this.$set(this.form, "postIds", response.postIds)
this.$set(this.form, "roleIds", response.roleIds)
this.open = true
this.title = "修改类型"
this.form.password = ""
})
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "类型密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
}).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value)
})
}).catch(() => {})
},
/** 分配角色操作 */
handleAuthRole: function(row) {
const userId = row.userId
this.$router.push("/system/user-auth/role/" + userId)
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.userId != undefined) {
updateUser(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addUser(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const userIds = row.userId || this.ids
this.$modal.confirm('是否确认删除类型编号为"' + userIds + '"的数据项?').then(function() {
return delUser(userIds)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => {})
},
/** 导出按钮操作 */
handleExport() {
this.download('system/user/export', {
...this.queryParams
}, `user_${new Date().getTime()}.xlsx`)
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "类型导入"
this.upload.open = true
},
/** 下载模板操作 */
importTemplate() {
this.download('system/user/importTemplate', {
}, `user_template_${new Date().getTime()}.xlsx`)
},
//
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
},
//
handleFileSuccess(response, file, fileList) {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
this.getList()
},
//
submitFileForm() {
this.$refs.upload.submit()
}
}
}
</script>

@ -0,0 +1,321 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme">
<!--设备档案-->
<pane size="84">
<el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="预警时间">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd hh:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item label="预警等级" prop="level">
<el-select v-model="queryParams.level" placeholder="预警等级" clearable style="width: 240px">
<el-option v-for="dict in dict.type.warning_level" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="处理状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.alert_message_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:files:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:files:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['device:files:import']">导入</el-button>
</el-col>
</el-row> -->
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column
label="序号"
width="60"
type="index"
></el-table-column>
<el-table-column label="预警时间" align="center" key="occurTime" prop="occurTime" />
<el-table-column label="预警等级" align="center" key="level" prop="level" :show-overflow-tooltip="true" />
<el-table-column label="预警信息" align="center" key="version" prop="version" :show-overflow-tooltip="true" />
<el-table-column label="预警状态" align="center" key="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.alert_message_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="处理人" align="center" key="handler" prop="handler" width="120" />
<el-table-column label="处理时间" align="center" prop="handleTime" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.handleTime) }}</span>
</template>
</el-table-column>
<el-table-column label="解决方案" align="center" key="solution" prop="solution" :show-overflow-tooltip="true" />
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" v-if="scope.row.status == 'UNHANDLED'" type="text" @click="handleUpdate(scope.row)" v-hasPermi="['device:files:edit']">去处理</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
</el-col>
</pane>
</splitpanes>
</el-row>
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body :close-on-click-modal="false">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="解决人" prop="handler">
<el-input v-model="form.handler" placeholder="请输入解决人" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="解决方法" prop="solution">
<el-input v-model="form.solution" placeholder="请输入解决方法" type="textarea" :rows="3" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getDict, list, getInfo, del, add, update } from "@/api/inMonitoring/message"
import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
export default {
name: "User",
dicts: ['device_disable', 'sys_user_sex', 'warning_level','alert_message_status'],
components: { Treeselect, Splitpanes, Pane },
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
dataList: null,
//
title: "",
//
deptOptions: undefined,
//
enabledDeptOptions: undefined,
//
open: false,
//
deptName: undefined,
//
initPassword: undefined,
//
dateRange: [],
//
postOptions: [],
//
roleOptions: [],
//
form: {},
defaultProps: {
children: "children",
label: "label"
},
//
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
updateSupport: 0,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/equipment/import"
},
//
queryParams: {
pageNum: 1,
pageSize: 10,
name: undefined,
status: undefined
},
//
rules: {
handler: [
{ required: true, message: "解决人不能为空", trigger: "blur" },
],
solution: [
{ required: true, message: "解决方法不能为空", trigger: "blur" }
]
}
}
},
watch: {
//
deptName(val) {
this.$refs.tree.filter(val)
}
},
created() {
this.getList()
},
methods: {
/** 查询设备列表 */
getList() {
this.loading = true
list({minTime:this.dateRange[0],maxTime:this.dateRange[1],...this.queryParams}).then(response => {
this.dataList = response.rows
this.total = response.total
this.loading = false
}
)
},
upImage(fileList){
console.log(fileList)
this.form.image = fileList
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
id: undefined,
deptId: undefined,
name: undefined,
nickName: undefined,
password: undefined,
phonenumber: undefined,
email: undefined,
sex: undefined,
status: "0",
remark: undefined,
postIds: [],
roleIds: []
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.resetForm("queryForm")
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length != 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加设备"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
this.form = {...row}
this.open = true
this.title = "处理"
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != undefined) {
update(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
add(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除设备ID为"' + Ids + '"的数据项?').then(function() {
return del(Ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => {})
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "设备导入"
this.upload.open = true
},
/** 下载模板操作 */
importTemplate() {
this.download('system/user/importTemplate', {
}, `user_template_${new Date().getTime()}.xlsx`)
},
//
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
},
//
handleFileSuccess(response, file, fileList) {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
this.getList()
},
//
submitFileForm() {
this.$refs.upload.submit()
}
}
}
</script>

@ -0,0 +1,445 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme">
<!--设备档案-->
<pane size="84">
<el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="预警级别">
<el-select v-model="queryParams.severity" placeholder="请选择级别" style="width: 100%">
<el-option v-for="dict in dict.type.warning_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['device:files:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['device:files:remove']">删除</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column
label="序号"
width="60"
type="index"
></el-table-column>
<el-table-column label="名称" align="center" key="ruleName" prop="ruleName" width="120"/>
<el-table-column label="描述" align="center" key="description" prop="description" width="240" :show-overflow-tooltip="true" />
<el-table-column label="触发条件" align="center" key="alertTemplate" prop="alertTemplate" width="240" :show-overflow-tooltip="true" />
<el-table-column label="预警级别" align="center" key="severity" prop="severity" width="120" />
<el-table-column label="预警方式" align="center" key="alertWay" prop="alertWay" width="120" :show-overflow-tooltip="true" />
<el-table-column label="预警邮箱" align="center" key="alertStation" prop="alertStation" width="200" :show-overflow-tooltip="true" />
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:files:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['device:files:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
</el-col>
</pane>
</splitpanes>
</el-row>
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body :close-on-click-modal="false">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="规则名称" prop="ruleName">
<el-input v-model="form.ruleName" placeholder="请输入设备名称" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="描述" prop="description">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="触发条件" prop="compareValue1">
<el-col :span="6">
<el-select v-model="form.paramName" placeholder="请选择" style="width: 100%">
<el-option v-for="dict in byTableData" :key="dict.columnName" :label="dict.paramName" :value="dict.columnName"></el-option>
</el-select>
</el-col>
<el-col :span="6">
<el-select v-model="form.operator" placeholder="请选择" style="width: 100%">
<el-option v-for="dict in dict.type.waming_rules" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-col>
<el-col :span="5">
<el-form-item label="" prop="compareValue1" label-width="0">
<el-input v-model="form.compareValue1" placeholder="请输入" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="1" v-if="form.operator == 'between'">
<span>~</span>
</el-col>
<el-col :span="5" v-if="form.operator == 'between'">
<el-form-item label="" prop="compareValue2" label-width="0">
<el-input v-model="form.compareValue2" placeholder="请输入" maxlength="30" />
</el-form-item>
</el-col>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="预警级别" prop="severity">
<el-select v-model="form.severity" placeholder="请选择级别" style="width: 100%">
<el-option v-for="dict in dict.type.warning_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<!-- <el-col :span="24">
<el-form-item label="预警消息" prop="message">
<el-input v-model="form.message" type="textarea" :rows="3" placeholder="请输入内容" />
</el-form-item>
</el-col> -->
<el-col :span="24">
<el-form-item label="是否邮箱" prop="alertWay">
<el-select v-model="form.alertWay" placeholder="启用状态" clearable>
<el-option v-for="dict in alertWayOptions" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.alertWay == 'email'">
<el-form-item label="邮箱" prop="alertStation">
<el-input v-model="form.alertStation" placeholder="请输入邮箱" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</span>
</el-dialog>
<!-- 设备导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的设备档案
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { list, del, add, update, byTable } from "@/api/inMonitoring/rules"
import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
export default {
name: "User",
dicts: ['warning_level', 'device_disable', 'waming_rules'],
components: { Treeselect, Splitpanes, Pane },
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
dataList: null,
//
title: "",
//
deptOptions: undefined,
//
enabledDeptOptions: undefined,
//
open: false,
//
deptName: undefined,
//
initPassword: undefined,
//
dateRange: [],
//
postOptions: [],
//
roleOptions: [],
//
form: {
id: undefined,
ruleName: undefined,
description: undefined,
paramName: undefined,
operator: undefined,
compareValue1: undefined,
compareValue2: undefined,
severity: undefined,
message: undefined,
alertWay: 'noemail',
alertStation: '',
status: "0"
},
//
byTableData: [],
alertWayOptions: [
{
value: 'noemail',
label: "否"
},
{
value: 'email',
label: "是"
}
],
defaultProps: {
children: "children",
label: "label"
},
//
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
updateSupport: 0,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/equipment/import"
},
//
queryParams: {
pageNum: 1,
pageSize: 10,
name: undefined,
status: undefined
},
//
rules: {
ruleName: [
{ required: true, message: "规则名称不能为空", trigger: "blur" }
],
description: [
{ required: true, message: "规则描述不能为空", trigger: "blur" },
],
alertWay: [
{ required: true, message: "设备类型不能为空", trigger: "blur" }
],
severity: [
{ required: true, message: "设备级别不能为空", trigger: "blur" },
],
message: [
{ required: true, message: "预警消息不能为空", trigger: "blur" }
],
status: [
{ required: true, message: "状态不能为空", trigger: "blur" },
],
paramName: [
{ required: true, message: "请选择", trigger: "blur" },
],
operator: [
{ required: true, message: "请选择", trigger: "blur" },
],
compareValue1: [
{ required: true, message: "请输入", trigger: "blur" },
],
compareValue2: [
{ required: true, message: "请输入", trigger: "blur" },
],
alertStation: [
{ required: true, message: "请输入", trigger: "blur" },
{
pattern: /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/,
message: "请输入正确的邮箱",
trigger: "blur"
}
]
}
}
},
watch: {
//
deptName(val) {
this.$refs.tree.filter(val)
}
},
created() {
this.getList()
this.getByTable()
},
methods: {
/** 查询设备列表 */
getList() {
this.loading = true
list({minTime:this.dateRange[0],maxTime:this.dateRange[1],...this.queryParams}).then(response => {
this.dataList = response.rows
this.total = response.total
this.loading = false
}
)
},
getByTable() {
this.loading = true
byTable().then(response => {
console.log("%c 🇻🇳: getList -> response ", "font-size:16px;background-color:#c9f364;color:black;", response)
this.byTableData = response.data
this.loading = false
}
)
},
upImage(fileList){
console.log(fileList)
this.form.image = fileList
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
email: undefined,
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.resetForm("queryForm")
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length != 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加设备"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
this.form = {...row}
this.open = true
this.title = "修改"
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
let form = {...this.form}
this.form.alertRule = {
ruleName: form.ruleName,
description: form.description,
alertStation: form.alertStation ? form.alertStation : "",
alertWay: form.alertWay,
severity: form.severity,
enable:0
}
this.form.alertRuleConditionList = [{
paramName: form.paramName,
compareValue: form.compareValue2?form.compareValue1+','+form.compareValue2:form.compareValue1,
operator: form.operator
}]
if (this.form.id != undefined) {
update(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
add(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除设备ID为"' + Ids + '"的数据项?').then(function() {
return del(Ids)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => {})
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "设备导入"
this.upload.open = true
},
/** 下载模板操作 */
importTemplate() {
this.download('system/user/importTemplate', {
}, `user_template_${new Date().getTime()}.xlsx`)
},
//
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
},
//
handleFileSuccess(response, file, fileList) {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
this.getList()
},
//
submitFileForm() {
this.$refs.upload.submit()
}
}
}
</script>

@ -0,0 +1,308 @@
<template>
<div class="dashboard-editor-container">
<el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<div class="card-title"><i class="el-icon-data-line"></i>预警信息统计</div>
<div class="data-overview">
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<div class="card-title"><i class="el-icon-pie-chart"></i>检测设备信息</div>
<pie-chart />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper overflow-auto">
<div class="card-title"><i class="el-icon-monitor"></i>设备预警信息</div>
<div class="div0">
<div class="div1" v-for="(alert, index) in alerts" :key="index" :class="`alert-level-${alert.level}`">
<dv-border-box-13 class="div2">
<el-row>
<el-col span="12">
<span class="alert-lable">预警时间:{{ alert.time }}</span>
</el-col>
<el-col span="12">
<span class="alert-lable">设备名称:{{ alert.deviceName }}</span>
</el-col>
<el-col span="12">
<span class="alert-lable">设备位置:{{ alert.deviceLocation }}</span>
</el-col>
<el-col span="12">
<span class="alert-lable">预警等级:<span class="alert-lable" :style="{ color: getLevelColor(alert.level) }">{{ alert.level }}</span></span>
</el-col>
<el-col span="12">
<span class="alert-lable">预警信息:{{ alert.message }}</span>
</el-col>
<el-col span="12">
<span class="alert-lable">预警状态:{{ alert.status }}</span>
</el-col>
</el-row>
</dv-border-box-13>
</div>
</div>
</div>
</el-col>
</el-row>
<el-row style="background:#fff;padding:16px;">
<div class="card-title"><i class="el-icon-s-data"></i> 设备状态监控</div>
<dv-scroll-board :config="scrollConfig" style="height:220px;" />
</el-row>
</div>
</template>
<script>
import PanelGroup from './dashboard/PanelGroup'
import LineChart from './dashboard/LineChart'
import RaddarChart from './dashboard/RaddarChart'
import PieChart from './dashboard/PieChart'
import BarChart from './dashboard/BarChart'
import digital from './dashboard/digital'
const lineChartData = {
newVisitis: {
expectedData: [100, 120, 161, 134, 105, 160, 165],
actualData: [120, 82, 91, 154, 162, 140, 145]
},
messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140],
actualData: [180, 160, 151, 106, 145, 150, 130]
},
purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100],
actualData: [120, 90, 100, 138, 142, 130, 130]
},
shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160],
actualData: [120, 82, 91, 154, 162, 140, 130]
}
}
export default {
name: 'Index',
components: {
PanelGroup,
LineChart,
RaddarChart,
PieChart,
BarChart,
digital
},
data() {
return {
lineChartData: lineChartData.newVisitis,
scrollConfig:{
header: ['设备名称', '设备位置', 'CPU使用率','内存使用率','温度', '健康度', '设备运行时长','采集时间'],
data: [
['行1列1', '行1列2', '行1列3', '行1列4', '行1列5', '行1列6','行1列7', '行1列8'],
['行2列1', '行2列2', '行2列3', '行2列4', '行2列5', '行2列6','行2列7', '行2列8'],
['行3列1', '行3列2', '行3列3', '行3列4', '行3列5', '行3列6','行3列7', '行3列8'],
['行4列1', '行4列2', '行4列3', '行4列4', '行4列5', '行4列6','行4列7', '行4列8'],
['行5列1', '行5列2', '行5列3', '行5列4', '行5列5', '行5列6','行5列7', '行5列8'],
['行6列1', '行6列2', '行6列3', '行6列4', '行6列5', '行6列6','行6列7', '行6列8'],
['行7列1', '行7列2', '行7列3', '行7列4', '行7列5', '行7列6','行7列7', '行7列8'],
['行8列1', '行8列2', '行8列3', '行8列4', '行8列5', '行8列6','行8列7', '行8列8'],
['行9列1', '行9列2', '行9列3', '行9列4', '行9列5', '行9列6','行9列7', '行9列8'],
['行10列1', '行10列2', '行10列3', '行10列4', '行10列5', '行10列6','行10列7', '行10列8']
],
headerBGC:'#f8f8f9',
headerHeight:60,
oddRowBGC:'#f5f7fa',
evenRowBGC:'#fff',
},
alerts: [
{
time: '2021-10-16 14:54:11',
deviceName: 'PLC远程监控系统',
deviceLocation: '污水处理监控系统',
level: 1,
message: '2#电机运行状态等于1',
status: '触发值: 1'
},
{
time: '2021-10-16 14:54:04',
deviceName: 'PLC远程监控系统',
deviceLocation: '污水处理监控系统',
level: 0,
message: '2#电机运行状态报警恢复',
status: '触发值: 0'
},
{
time: '2021-10-16 14:54:11',
deviceName: 'PLC远程监控系统',
deviceLocation: '污水处理监控系统',
level: 1,
message: '2#电机运行状态等于1',
status: '触发值: 1'
},
{
time: '2021-10-16 14:54:04',
deviceName: 'PLC远程监控系统',
deviceLocation: '污水处理监控系统',
level: 0,
message: '2#电机运行状态报警恢复',
status: '触发值: 0'
},
//
]
}
},
methods: {
handleSetLineChartData(type) {
this.lineChartData = lineChartData[type]
},
getLevelColor(level) {
const levelColors = {
0: 'green',
1: 'orange',
2: 'red'
};
return levelColors[level] || 'black'; //
}
}
}
</script>
<style lang="scss" scoped>
.dashboard-editor-container {
padding: 32px;
background-color: rgb(240, 242, 245);
position: relative;
.chart-wrapper {
background: #fff;
padding: 16px;
margin-bottom: 32px;
height: 420px;
}
}
@media (max-width:1024px) {
.chart-wrapper {
padding: 8px;
}
}
.dv-scroll-board{
color: #3d3d3d;
}
.card-title {
font-size: 16px;
margin-bottom: 15px;
display: flex;
align-items: center;
color: #3d3d3d;
font-weight: bold;
}
.card-title i {
margin-right: 8px;
font-size: 18px;
}
.data-overview {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.data-item {
flex: 1;
min-width: 30%;
text-align: center;
padding: 15px 10px;
background: #f5f7fa;
border-radius: 8px;
transition: all 0.3s ease;
}
.data-item:hover {
background: #f1f2f4;
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.data-value {
font-size: 24px;
font-weight: bold;
margin: 10px 0;
color: #3d3d3d;
}
.data-label {
font-size: 14px;
color: #3d3d3d;
}
.alert-list .div0 {
list-style-type: none;
padding: 0;
}
.overflow-auto {
overflow: auto;
}
.alert-list {
background-color: #fff;
padding: 16px;
margin-bottom: 32px;
}
.alert-list .div1 {
display: flex;
justify-content: space-between;
}
.div1{
margin-bottom: 5px;
}
.div2{
padding: 20px 16px;
}
.alert-time, .alert-device-name, .alert-device-location, .alert-message, .alert-status {
flex: 1;
}
.alert-level {
flex: 0.5;
text-align: center;
}
</style>

@ -1,94 +1,132 @@
<template> <template>
<div class="dashboard-editor-container"> <div class="body">
<div class="container">
<el-row :gutter="32"> <!-- 上层三个模块并排 -->
<el-col :xs="24" :sm="24" :lg="8"> <div class="top-section">
<div class="chart-wrapper"> <!-- 预警信息统计 -->
<div class="card-title"><i class="el-icon-data-line"></i>预警信息统计</div> <div class="panel">
<div class="data-overview"> <div class="card">
<div class="data-item"> <div class="card-header">
<div class="data-label">预警总数</div> <h2 class="card-title"><i class="fas fa-exclamation-triangle"></i> 预警信息统计</h2>
<digital :configData="{number:[111]}" /> </div>
</div> <div class="stats-container">
<div class="data-item"> <div class="stat-card" :class="alertMessageData.yearCount == 0?'normal':''">
<div class="data-label">预警总数</div> <div class="stat-label">年预警总数</div>
<digital :configData="{number:[111]}" /> <div class="stat-value">{{ alertMessageData.yearCount }}</div>
</div> </div>
<div class="data-item"> <div class="stat-card" :class="alertMessageData.monthCount == 0?'normal':''">
<div class="data-label">预警总数</div> <div class="stat-label">月预警总数</div>
<digital :configData="{number:[111]}" /> <div class="stat-value">{{ alertMessageData.monthCount }}</div>
</div> </div>
<div class="data-item"> <!-- 等级预警 -->
<div class="data-label">预警总数</div> <div class="stat-card" :class="i.count == 0?'normal':i.count>10?'warning':''" v-for="(i,k) in alertMessageData.levelCount" :key="k">
<digital :configData="{number:[111]}" /> <div class="stat-label">{{ `等级${i.level}预警` }}</div>
</div> <div class="stat-value">{{ i.count }}</div>
<div class="data-item"> </div>
<div class="data-label">预警总数</div> <!-- 设备预警 -->
<digital :configData="{number:[111]}" /> <div class="stat-card" :class="i.count == 0?'normal':i.count>10?'warning':''" v-for="(i,k) in alertMessageData.typeCount" :key="k">
</div> <div class="stat-label">{{ `${i.name}预警` }}</div>
<div class="data-item"> <div class="stat-value">{{ i.count }}</div>
<div class="data-label">预警总数</div> </div>
<digital :configData="{number:[111]}" /> </div>
</div> </div>
<div class="data-item">
<div class="data-label">预警总数</div>
<digital :configData="{number:[111]}" />
</div> </div>
<div class="data-item">
<div class="data-label">预警总数</div> <!-- 检测设备信息 -->
<digital :configData="{number:[111]}" /> <div class="panel">
<div class="card">
<div class="card-header">
<h2 class="card-title"><i class="fas fa-microchip"></i> 检测设备信息</h2>
</div>
<ul class="device-list">
<li class="device-item" v-for="device in devices" :key="device.id" :class="device.status">
<div class="device-icon">
<i :class="device.icon"></i>
</div>
<div class="device-info">
<div class="device-name">{{ device.name }}</div>
<div class="device-details">{{ device.description }}</div>
</div>
<span :class="device.status === 'UNHANDLED' ? 'alert-badge' : 'normal-badge'">
{{ device.status === 'UNHANDLED' ? '预警中' : '正常' }}
</span>
</li>
</ul>
</div>
</div> </div>
<div class="data-item">
<div class="data-label">预警总数</div> <!-- 设备预警信息 -->
<digital :configData="{number:[111]}" /> <div class="panel">
<div class="card">
<div class="card-header">
<h2 class="card-title"><i class="fas fa-bell"></i> 设备预警信息</h2>
</div>
<ul class="device-list" v-infinite-scroll="loadMore" :infinite-scroll-disabled="isLoading || noMore" infinite-scroll-distance="50" infinite-scroll-delay="300">
<li class="device-item" v-for="alert in alerts" :key="alert.id" :class="alert.status === 'UNHANDLED' ? 'warning' : 'normal'" >
<div class="device-icon">
<i :class="alert.status === 'UNHANDLED' ? 'fas fa-exclamation-circle' : 'fas fa-check-circle'"></i>
</div>
<div class="device-info">
<div class="device-name">{{ alert.name }}</div>
<div class="device-details">
<div>预警时间: {{ parseTime(alert.occurTime) }}</div>
<div>设备位置: {{ alert.location }}</div>
<div>预警信息: {{ alert.message }}</div>
</div>
</div>
<span :class="alert.status === 'UNHANDLED' ? 'alert-badge' : 'normal-badge'">
{{ '等级'+alert.level }}
</span>
</li>
<p v-if="isLoading">加载中...</p>
<p v-if="noMore">没有更多了</p>
</ul>
</div>
</div> </div>
</div>
</div> </div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8"> <!-- 下层设备状态监控独立一行 -->
<div class="chart-wrapper"> <div class="bottom-section">
<div class="card-title"><i class="el-icon-pie-chart"></i>检测设备信息</div> <div class="card full-width">
<pie-chart /> <div class="card-header">
</div> <h2 class="card-title"><i class="fas fa-desktop"></i> 设备状态监控</h2>
</el-col> <div class="last-update">最后更新: {{ lastUpdate }}</div>
<el-col :xs="24" :sm="24" :lg="8"> </div>
<div class="chart-wrapper"> <div class="table-container">
<div class="card-title"><i class="el-icon-monitor"></i>设备预警信息</div> <table>
<thead>
<div class="div0"> <tr>
<div class="div1" v-for="(alert, index) in alerts" :key="index" :class="`alert-level-${alert.level}`"> <th v-for="header in tableHeaders" :key="header">{{ header }}</th>
<dv-border-box-13 class="div2"> </tr>
<el-row> </thead>
<el-col span="12"> <tbody>
<span class="alert-lable">预警时间:{{ alert.time }}</span> <tr v-for="device in deviceStatus" :key="device.id">
</el-col> <td>{{ device.name }}</td>
<el-col span="12"> <td>{{ device.location }}</td>
<span class="alert-lable">设备名称:{{ alert.deviceName }}</span> <td>
</el-col> <span :class="getCpuStatus(device.cpuUsage)"></span>
<el-col span="12"> {{ device.cpuUsage }}%
<span class="alert-lable">设备位置:{{ alert.deviceLocation }}</span> </td>
</el-col> <td>
<el-col span="12"> <span :class="getMemoryStatus(device.memoryUsage)"></span>
<span class="alert-lable">预警等级:<span class="alert-lable" :style="{ color: getLevelColor(alert.level) }">{{ alert.level }}</span></span> {{ device.memoryUsage }}%
</el-col> </td>
<el-col span="12"> <td>{{ device.temperature }}°C</td>
<span class="alert-lable">预警信息:{{ alert.message }}</span> <td>
</el-col> <div class="health-bar">
<el-col span="12"> <div class="health-fill" :class="getHealthStatus(device.health)"></div>
<span class="alert-lable">预警状态:{{ alert.status }}</span> </div>
</el-col> {{ device.health }}%
</el-row> </td>
</dv-border-box-13> <td>{{ device.uptime }}</td>
<td>{{ device.collectionTime }}</td>
</tr>
</tbody>
</table>
</div>
</div> </div>
</div>
</div> </div>
</el-col> </div>
</el-row>
<el-row style="background:#fff;padding:16px;">
<div class="card-title"><i class="el-icon-s-data"></i> 设备状态监控</div>
<dv-scroll-board :config="scrollConfig" style="height:220px;" />
</el-row>
</div> </div>
</template> </template>
@ -99,25 +137,12 @@ import RaddarChart from './dashboard/RaddarChart'
import PieChart from './dashboard/PieChart' import PieChart from './dashboard/PieChart'
import BarChart from './dashboard/BarChart' import BarChart from './dashboard/BarChart'
import digital from './dashboard/digital' import digital from './dashboard/digital'
import { statistic, byEquType, listMonitor, alertMessageTimes } from "@/api/index/index"
const lineChartData = { import { getToken } from "@/utils/auth"
newVisitis: { import Treeselect from "@riophae/vue-treeselect"
expectedData: [100, 120, 161, 134, 105, 160, 165], import "@riophae/vue-treeselect/dist/vue-treeselect.css"
actualData: [120, 82, 91, 154, 162, 140, 145] import { Splitpanes, Pane } from "splitpanes"
}, import "splitpanes/dist/splitpanes.css"
messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140],
actualData: [180, 160, 151, 106, 145, 150, 130]
},
purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100],
actualData: [120, 90, 100, 138, 142, 130, 130]
},
shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160],
actualData: [120, 82, 91, 154, 162, 140, 130]
}
}
export default { export default {
name: 'Index', name: 'Index',
@ -131,170 +156,445 @@ export default {
}, },
data() { data() {
return { return {
lineChartData: lineChartData.newVisitis, totalAlerts: 111,
scrollConfig:{ activeAlerts: 42,
header: ['设备名称', '设备位置', 'CPU使用率','内存使用率','温度', '健康度', '设备运行时长','采集时间'], resolvedAlerts: 69,
data: [ lastUpdate: new Date().toLocaleString(),
['行1列1', '行1列2', '行1列3', '行1列4', '行1列5', '行1列6','行1列7', '行1列8'],
['行2列1', '行2列2', '行2列3', '行2列4', '行2列5', '行2列6','行2列7', '行2列8'], isLoading: false, //
['行3列1', '行3列2', '行3列3', '行3列4', '行3列5', '行3列6','行3列7', '行3列8'], noMore: false, //
['行4列1', '行4列2', '行4列3', '行4列4', '行4列5', '行4列6','行4列7', '行4列8'], page: 1, //
['行5列1', '行5列2', '行5列3', '行5列4', '行5列5', '行5列6','行5列7', '行5列8'], devices: [
['行6列1', '行6列2', '行6列3', '行6列4', '行6列5', '行6列6','行6列7', '行6列8'], { id: 1, name: 'Forecasts', description: '预测分析系统', status: 'normal', icon: 'fas fa-chart-line' },
['行7列1', '行7列2', '行7列3', '行7列4', '行7列5', '行7列6','行7列7', '行7列8'], { id: 2, name: 'Gold', description: '核心处理单元', status: 'warning', icon: 'fas fa-server' },
['行8列1', '行8列2', '行8列3', '行8列4', '行8列5', '行8列6','行8列7', '行8列8'], { id: 3, name: 'Industries', description: '工业控制系统', status: 'normal', icon: 'fas fa-industry' }
['行9列1', '行9列2', '行9列3', '行9列4', '行9列5', '行9列6','行9列7', '行9列8'], ],
['行10列1', '行10列2', '行10列3', '行10列4', '行10列5', '行10列6','行10列7', '行10列8'] //
], alerts: [],
headerBGC:'#f8f8f9', //
headerHeight:60, alertMessageData: [],
oddRowBGC:'#f5f7fa', tableHeaders: ['设备名称', '设备位置', 'CPU使用率', '内存使用率', '温度', '健康度', '设备运行时长', '采集时间'],
evenRowBGC:'#fff', deviceStatus: [
}, {
alerts: [ id: 1,
{ name: 'PLC控制系统',
time: '2021-10-16 14:54:11', location: '主控室A区',
deviceName: 'PLC远程监控系统', cpuUsage: 45,
deviceLocation: '污水处理监控系统', memoryUsage: 62,
level: 1, temperature: 42,
message: '2#电机运行状态等于1', health: 85,
status: '触发值: 1' uptime: '125天8小时',
}, collectionTime: '2021-10-16 15:20:00'
{ },
time: '2021-10-16 14:54:04', {
deviceName: 'PLC远程监控系统', id: 2,
deviceLocation: '污水处理监控系统', name: '数据采集器',
level: 0, location: '污水处理区',
message: '2#电机运行状态报警恢复', cpuUsage: 78,
status: '触发值: 0' memoryUsage: 85,
}, temperature: 58,
{ health: 65,
time: '2021-10-16 14:54:11', uptime: '89天12小时',
deviceName: 'PLC远程监控系统', collectionTime: '2021-10-16 15:22:00'
deviceLocation: '污水处理监控系统', },
level: 1, {
message: '2#电机运行状态等于1', id: 3,
status: '触发值: 1' name: '监控服务器',
}, location: '数据中心',
{ cpuUsage: 32,
time: '2021-10-16 14:54:04', memoryUsage: 45,
deviceName: 'PLC远程监控系统', temperature: 38,
deviceLocation: '污水处理监控系统', health: 92,
level: 0, uptime: '210天3小时',
message: '2#电机运行状态报警恢复', collectionTime: '2021-10-16 15:25:00'
status: '触发值: 0' },
}, {
// id: 4,
name: '网络交换机',
location: '通信机房',
cpuUsage: 15,
memoryUsage: 28,
temperature: 35,
health: 95,
uptime: '156天7小时',
collectionTime: '2021-10-16 15:18:00'
}
] ]
} }
}, },
methods: { methods: {
handleSetLineChartData(type) { getCpuStatus(usage) {
this.lineChartData = lineChartData[type] if (usage < 50) return 'status-indicator status-good';
if (usage < 80) return 'status-indicator status-warning';
return 'status-indicator status-critical';
}, },
getLevelColor(level) { getMemoryStatus(usage) {
const levelColors = { if (usage < 60) return 'status-indicator status-good';
0: 'green', if (usage < 85) return 'status-indicator status-warning';
1: 'orange', return 'status-indicator status-critical';
2: 'red' },
}; getHealthStatus(health) {
return levelColors[level] || 'black'; // if (health >= 80) return 'health-good';
} if (health >= 60) return 'health-warning';
} return 'health-critical';
},
getstatistic() {
this.loading = true
statistic().then(response => {
this.alerts = response.rows
this.loading = false
}
)
},
getbyEquType() {
this.loading = true
byEquType().then(response => {
this.loading = false
}
)
},
getlistMonitor() {
this.loading = true
listMonitor().then(response => {
this.loading = false
}
)
},
getalertMessageTimes() {
this.loading = true
alertMessageTimes().then(response => {
this.alertMessageData = response.data
this.loading = false
}
)
},
async loadMore() {
console.log("%c 🎧: loadMore -> this.isLoading || this.noMore ", "font-size:16px;background-color:#64b738;color:white;", this.isLoading , this.noMore)
if (this.isLoading || this.noMore) return;
this.isLoading = true;
try {
const res = await statistic({page:this.page}); // API
if (res.rows.length < 10) { // 10
this.noMore = true;
} else {
this.alerts = [...this.alerts, ...res.rows];
this.page++;
}
} catch (error) {
console.error('加载失败:', error);
} finally {
this.isLoading = false;
}
},
},
created() {
// this.getstatistic()
this.getbyEquType()
this.getlistMonitor()
this.getalertMessageTimes()
},
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.dashboard-editor-container {
padding: 32px;
background-color: rgb(240, 242, 245);
position: relative;
.chart-wrapper {
background: #fff;
padding: 16px;
margin-bottom: 32px;
height: 420px;
}
}
@media (max-width:1024px) { .body {
.chart-wrapper { background-color: #f5f7fa;
padding: 8px; color: #333;
} line-height: 1.6;
} padding: 20px;
.dv-scroll-board{ }
color: #3d3d3d;
} .header {
.card-title { text-align: center;
font-size: 16px; margin-bottom: 30px;
margin-bottom: 15px; }
display: flex;
align-items: center; .header h1 {
color: #3d3d3d; color: #2c3e50;
font-weight: bold; margin-bottom: 10px;
} font-size: 28px;
}
.card-title i {
margin-right: 8px; .header p {
font-size: 18px; color: #7f8c8d;
} font-size: 16px;
}
.data-overview {
display: flex; .container {
flex-wrap: wrap; display: flex;
gap: 15px; flex-direction: column;
} gap: 20px;
}
.data-item {
flex: 1; .top-section {
min-width: 30%; display: flex;
text-align: center; gap: 20px;
padding: 15px 10px; }
background: #f5f7fa;
border-radius: 8px; .bottom-section {
transition: all 0.3s ease; display: flex;
} flex-direction: column;
gap: 20px;
.data-item:hover { }
background: #f1f2f4;
transform: translateY(-3px); .panel {
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); flex: 1;
} display: flex;
flex-direction: column;
.data-value { gap: 20px;
font-size: 24px; }
font-weight: bold;
margin: 10px 0; .card {
color: #3d3d3d; background: white;
} border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
.data-label { padding: 20px;
font-size: 14px; transition: transform 0.3s ease, box-shadow 0.3s ease;
color: #3d3d3d; height: 100%;
} }
.alert-list .div0 {
list-style-type: none; .card:hover {
padding: 0; transform: translateY(-5px);
} box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12);
}
.alert-list .div1 {
display: flex; .card-header {
justify-content: space-between; display: flex;
} justify-content: space-between;
.div1{ align-items: center;
margin-bottom: 5px; margin-bottom: 15px;
} padding-bottom: 10px;
.div2{ border-bottom: 1px solid #eaeaea;
padding: 20px 16px; }
}
.card-title {
.alert-time, .alert-device-name, .alert-device-location, .alert-message, .alert-status { font-size: 18px;
flex: 1; font-weight: 600;
} color: #2c3e50;
display: flex;
.alert-level { align-items: center;
flex: 0.5; gap: 8px;
text-align: center; }
}
.card-title i {
color: #3498db;
}
.stats-container {
display: grid;
justify-content: space-between;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
overflow-y: auto;
overflow-x: hidden;
height: 255px;
}
.stat-card {
flex: 1;
background: linear-gradient(135deg, #3498db, #2c3e50);
color: white;
border-radius: 10px;
padding: 12px;
text-align: center;
box-shadow: 0 4px 8px rgba(52, 152, 219, 0.3);
}
.stat-card.warning {
background: linear-gradient(135deg, #e74c3c, #c0392b);
box-shadow: 0 4px 8px rgba(231, 76, 60, 0.3);
}
.stat-card.normal {
background: linear-gradient(135deg, #2ecc71, #27ae60);
box-shadow: 0 4px 8px rgba(46, 204, 113, 0.3);
}
.stat-value {
font-size: 32px;
font-weight: 700;
margin: 10px 0;
}
.stat-label {
font-size: 14px;
opacity: 0.9;
}
.device-list {
list-style: none;
overflow-y: auto;
overflow-x: hidden;
max-height: 255px;
}
.device-item {
display: flex;
align-items: center;
padding: 12px 15px;
margin-bottom: 10px;
background: #f8f9fa;
border-radius: 8px;
border-left: 4px solid #3498db;
transition: all 0.2s;
}
.device-item:hover {
background: #edf2f7;
transform: translateX(5px);
}
.device-item.warning {
border-left-color: #e74c3c;
}
.device-item.normal {
border-left-color: #2ecc71;
}
.device-icon {
width: 40px;
height: 40px;
background: #3498db;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 15px;
color: white;
}
.device-item.warning .device-icon {
background: #e74c3c;
}
.device-item.normal .device-icon {
background: #2ecc71;
}
.device-info {
flex: 1;
}
.device-name {
font-weight: 600;
margin-bottom: 5px;
}
.device-details {
font-size: 13px;
color: #666;
}
.alert-badge {
background: #e74c3c;
color: white;
padding: 3px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.normal-badge {
background: #2ecc71;
color: white;
padding: 3px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.table-container {
overflow-x: auto;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
table {
width: 100%;
border-collapse: collapse;
background: white;
}
th {
background: #2c3e50;
color: white;
padding: 15px 12px;
text-align: left;
font-weight: 600;
}
td {
padding: 12px;
border-bottom: 1px solid #eaeaea;
}
tr:hover {
background-color: #f5f7fa;
}
.status-indicator {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 5px;
}
.status-good {
background-color: #2ecc71;
}
.status-warning {
background-color: #f39c12;
}
.status-critical {
background-color: #e74c3c;
}
.health-bar {
height: 6px;
background: #ecf0f1;
border-radius: 3px;
overflow: hidden;
}
.health-fill {
height: 100%;
border-radius: 3px;
}
.health-good {
background: #2ecc71;
width: 85%;
}
.health-warning {
background: #f39c12;
width: 65%;
}
.health-critical {
background: #e74c3c;
width: 40%;
}
.full-width {
width: 100%;
}
@media (max-width: 1024px) {
.top-section {
flex-direction: column;
}
.stats-container {
flex-direction: column;
}
}
</style> </style>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save