邮件API

This commit is contained in:
2025-11-16 19:58:51 +08:00
parent 9d442b017a
commit 3b3d6dea66
91 changed files with 6017 additions and 413 deletions

View File

@@ -1,19 +1,31 @@
package com.mini.capi.api.job;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mini.capi.biz.domain.BizDeviceInfo;
import com.mini.capi.biz.domain.BizMonitorAccount;
import com.mini.capi.biz.domain.BizMonitorHost;
import com.mini.capi.biz.domain.BizServerInfo;
import com.mini.capi.biz.service.BizDeviceInfoService;
import com.mini.capi.biz.service.BizMonitorAccountService;
import com.mini.capi.biz.service.BizMonitorHostService;
import com.mini.capi.biz.service.BizServerInfoService;
import com.mini.capi.model.ApiResult;
import com.mini.capi.model.info.CpuInfo;
import com.mini.capi.model.info.DiskInfo;
import com.mini.capi.model.info.ServerInfo;
import com.mini.capi.utils.NetworkUtils;
import com.mini.capi.utils.SystemInfoUtil;
import com.mini.capi.utils.vId;
import jakarta.annotation.Resource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -25,6 +37,16 @@ public class jobController {
@Resource
private BizMonitorHostService bizMonitorHostService;
@Resource
private BizMonitorAccountService bizMonitorAccountService;
@Resource
private BizServerInfoService bizServerInfoService;
@Resource
private BizDeviceInfoService bizDeviceInfoService;
// 注入配置好的线程池
@Resource(name = "hostMonitorExecutor")
private ThreadPoolTaskExecutor hostMonitorExecutor;
@@ -44,6 +66,7 @@ public class jobController {
boolean isReachable = NetworkUtils.isNetworkReachable(monitorHost.getIpAddress());
monitorHost.setUstatus(isReachable ? "1" : "0");
if (isReachable) {
syncServerInfo(monitorHost);
monitorHost.setLastOnlineTime(LocalDateTime.now());
}
bizMonitorHostService.update(monitorHost, updateWrapper);
@@ -53,7 +76,6 @@ public class jobController {
}, hostMonitorExecutor); // 指定使用配置的线程池
futures.add(future);
}
try {
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.get(60, TimeUnit.SECONDS); // 超时时间可根据业务调整
@@ -62,4 +84,68 @@ public class jobController {
return ApiResult.error(101, e.getMessage());
}
}
public void syncServerInfo(BizMonitorHost host) {
try {
QueryWrapper<BizMonitorAccount> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("host_id", host.getHostId()).eq("ssh_username", "ogsapp");
BizMonitorAccount account = bizMonitorAccountService.getOne(queryWrapper);
if (account != null) {
CpuInfo cpuInfo = SystemInfoUtil.getCpuMemUsage(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), account.getSshPassword());
ServerInfo info = SystemInfoUtil.getServerBasicInfo(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), account.getSshPassword(), host.getIpAddress());
List<DiskInfo> diskInfos = SystemInfoUtil.getDiskInfos(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), account.getSshPassword());
syncDeviceInfo(host, diskInfos);
Optional<BizServerInfo> serverInfoOpt = Optional.ofNullable(
bizServerInfoService.getOne(new QueryWrapper<BizServerInfo>().eq("host_id", host.getHostId()))
);
BizServerInfo serverInfo = serverInfoOpt.orElseGet(() -> {
BizServerInfo newInfo = new BizServerInfo();
newInfo.setHostId(host.getHostId()); // 初始化唯一标识
return newInfo;
});
serverInfo.setUptime(info.getUptime());
serverInfo.setOs(info.getOs());
serverInfo.setKernelVersion(info.getKernelVersion());
serverInfo.setHostname(info.getHostname());
serverInfo.setIpAddress(info.getIpAddress());
serverInfo.setCpuModel(info.getCpuModel());
serverInfo.setMemoryTotal(info.getMemoryTotal());
serverInfo.setCpuUsage(cpuInfo.getCpuUsage());
serverInfo.setMemoryUsage(cpuInfo.getMemoryUsage());
serverInfo.setLastOnlineTime(LocalDateTime.now());
UpdateWrapper<BizServerInfo> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("host_id", host.getHostId());
bizServerInfoService.saveOrUpdate(serverInfo, updateWrapper);
}
} catch (Exception e) {
System.out.print(e.getMessage());
}
}
public void syncDeviceInfo(BizMonitorHost host, List<DiskInfo> diskInfos) {
for (DiskInfo diskInfo : diskInfos) {
Optional<BizDeviceInfo> deviceInfoOpt = Optional.ofNullable(
bizDeviceInfoService.getOne(new QueryWrapper<BizDeviceInfo>().eq("host_id", host.getHostId()).eq("device", diskInfo.getDevice()).eq("mount_point", diskInfo.getMountPoint()))
);
BizDeviceInfo deviceInfo = deviceInfoOpt.orElseGet(() -> {
BizDeviceInfo newInfo = new BizDeviceInfo();
newInfo.setHostId(host.getHostId()); // 初始化唯一标识
return newInfo;
});
deviceInfo.setDevice(diskInfo.getDevice());
deviceInfo.setMountPoint(diskInfo.getMountPoint());
deviceInfo.setTotalSize(diskInfo.getTotalSize());
deviceInfo.setUsedSize(diskInfo.getUsedSize());
deviceInfo.setUsageRate(diskInfo.getUsageRate());
deviceInfo.setLastOnlineTime(LocalDateTime.now());
UpdateWrapper<BizDeviceInfo> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("host_id", host.getHostId()).eq("device", diskInfo.getDevice()).eq("mount_point", diskInfo.getMountPoint());
bizDeviceInfoService.saveOrUpdate(deviceInfo, updateWrapper);
}
}
}

View File

@@ -14,13 +14,7 @@ public class sysController {
@Resource
private AppRuntimeInfo appRuntimeInfo;
@Resource
private AppPathInfo appPathInfo;
@Resource
private AppProcessInfo appProcessInfo;
@Resource
private AppNetworkInfo appNetworkInfo;
private sysService service;
/**
* 运行信息
@@ -28,35 +22,7 @@ public class sysController {
@GetMapping("getRunInfo")
public ApiResult<?> getRunInfo() {
try {
// 用构建者模式链式创建对象,避免重复的参数传递和构造函数调用
RunInfo runInfo = RunInfo.builder()
.runtimeInfo(RuntimeInfo.builder()
.appName(appRuntimeInfo.getAppName())
.serverPort(appRuntimeInfo.getServerPort())
.activeProfiles(appRuntimeInfo.getActiveProfiles())
.springBootVersion(appRuntimeInfo.getSpringBootVersion())
.jdkVersion(appRuntimeInfo.getJdkVersion())
.build())
.pathInfo(PathInfo.builder()
.workDir(appPathInfo.getWorkDir())
.jarDir(appPathInfo.getJarDir())
.resourceDir(appPathInfo.getResourceDir())
.build())
.processInfo(ProcessInfo.builder()
.pid(appProcessInfo.getPid())
.uptime(appProcessInfo.getUptime())
.usedHeapMemory(appProcessInfo.getUsedHeapMemory())
.maxHeapMemory(appProcessInfo.getMaxHeapMemory())
.jvmArgs(appProcessInfo.getJvmArgs())
.build())
.networkInfo(NetworkInfo.builder()
.hostName(appNetworkInfo.getHostName())
.localIp(appNetworkInfo.getLocalIp())
.allIps(appNetworkInfo.getAllIps())
.build())
.build();
return ApiResult.success(runInfo);
return ApiResult.success(service.getRunInfo());
} catch (Exception e) {
return ApiResult.error(101, e.getMessage());
}

View File

@@ -0,0 +1,54 @@
package com.mini.capi.api.sys;
import com.mini.capi.config.component.AppNetworkInfo;
import com.mini.capi.config.component.AppPathInfo;
import com.mini.capi.config.component.AppProcessInfo;
import com.mini.capi.config.component.AppRuntimeInfo;
import com.mini.capi.model.info.*;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@Service
public class sysService {
@Resource
private AppRuntimeInfo appRuntimeInfo;
@Resource
private AppPathInfo appPathInfo;
@Resource
private AppProcessInfo appProcessInfo;
@Resource
private AppNetworkInfo appNetworkInfo;
public RunInfo getRunInfo() throws Exception {
RunInfo runInfo = RunInfo.builder()
.runtimeInfo(RuntimeInfo.builder()
.appName(appRuntimeInfo.getAppName())
.serverPort(appRuntimeInfo.getServerPort())
.activeProfiles(appRuntimeInfo.getActiveProfiles())
.springBootVersion(appRuntimeInfo.getSpringBootVersion())
.jdkVersion(appRuntimeInfo.getJdkVersion())
.build())
.pathInfo(PathInfo.builder()
.workDir(appPathInfo.getWorkDir())
.jarDir(appPathInfo.getJarDir())
.resourceDir(appPathInfo.getResourceDir())
.build())
.processInfo(ProcessInfo.builder()
.pid(appProcessInfo.getPid())
.uptime(appProcessInfo.getUptime())
.usedHeapMemory(appProcessInfo.getUsedHeapMemory())
.maxHeapMemory(appProcessInfo.getMaxHeapMemory())
.jvmArgs(appProcessInfo.getJvmArgs())
.build())
.networkInfo(NetworkInfo.builder()
.hostName(appNetworkInfo.getHostName())
.localIp(appNetworkInfo.getLocalIp())
.allIps(appNetworkInfo.getAllIps())
.build())
.build();
return runInfo;
}
}

View File

@@ -1,20 +1,80 @@
package com.mini.capi.biz;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mini.capi.biz.domain.BizHomeUser;
import com.mini.capi.biz.service.BizHomeUserService;
import com.mini.capi.model.auth.LoginRequest;
import com.mini.capi.model.info.TodoHandleDTO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@Controller
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/biz")
public class LoginController {
@GetMapping("/login")
public String showLoginPage() {
return "login";
@Resource
private BizHomeUserService userService;
/**
* 登录
*/
@PostMapping("/userLogin")
public Map<String, Object> userLogin(@RequestBody LoginRequest loginRequest, HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> result = new HashMap<>();
try {
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
QueryWrapper<BizHomeUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", username).eq("password", password);
BizHomeUser user = userService.getOne(queryWrapper);
if (user != null) {
request.getSession().setAttribute("currentUser", user);
// 3.3 返回成功响应
result.put("success", true);
result.put("message", "登录成功");
} else {
result.put("success", false);
result.put("message", "账号或密码错误");
}
} catch (Exception e) {
result.put("success", false);
result.put("message", "服务器内部错误," + e.getMessage());
}
return result;
}
@GetMapping("/swagger")
public String redirectToSwagger() {
return "redirect:/swagger-ui/index.html";
/**
* 处理退出登录请求
* 对应前端 fetch('/logout', {method: 'POST'})
*/
@PostMapping("/logout")
public ResponseEntity<Void> logout(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
try {
// 3. 清除Session中的用户信息
if (session != null) {
session.removeAttribute("currentUser"); // 清除之前存入的currentUser
session.invalidate(); // 使Session失效
}
// 5. 返回成功响应200 OK
return ResponseEntity.ok().build();
} catch (Exception e) {
// 处理异常情况
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 设备存储信息表 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/bizDeviceInfo")
public class BizDeviceInfoController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 文件夹信息表 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/bizFileFolders")
public class BizFileFoldersController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 文件信息表 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/bizFiles")
public class BizFilesController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-14
*/
@RestController
@RequestMapping("/biz/bizHomeUser")
public class BizHomeUserController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 快捷登录系统信息表 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-15
*/
@RestController
@RequestMapping("/biz/bizQuickLogin")
public class BizQuickLoginController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 服务器信息表 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/bizServerInfo")
public class BizServerInfoController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 待办任务子表(关联主任务) 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/bizSubTask")
public class BizSubTaskController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* VIEW 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/bizTodoTaskView")
public class BizTodoTaskViewController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 数据表字段信息表 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/dataTableField")
public class DataTableFieldController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 数据表基础信息表 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@RestController
@RequestMapping("/biz/dataTableInfo")
public class DataTableInfoController {
}

View File

@@ -0,0 +1,83 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 设备存储信息表
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("biz_device_info")
public class BizDeviceInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 记录时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private String id;
/**
* 设备
*/
@TableField("device")
private String device;
/**
* 挂载点
*/
@TableField("mount_point")
private String mountPoint;
/**
* 总容量
*/
@TableField("total_size")
private String totalSize;
/**
* 已使用容量
*/
@TableField("used_size")
private String usedSize;
/**
* 使用率(%)
*/
@TableField("usage_rate")
private double usageRate;
/**
* 最后一次检测到在线的时间
*/
@TableField("last_online_time")
private LocalDateTime lastOnlineTime;
/**
* 主机唯一标识
*/
@TableField("host_id")
private String hostId;
}

View File

@@ -0,0 +1,74 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 文件夹信息表
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("biz_file_folders")
public class BizFileFolders implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 文件夹ID
*/
@TableId(value = "folder_id", type = IdType.AUTO)
private String folderId;
/**
* 文件夹名称
*/
@TableField("folder_name")
private String folderName;
/**
* 父文件夹ID0表示根目录
*/
@TableField("parent_id")
private Integer parentId;
/**
* 创建人ID关联用户表
*/
@TableField("creator_id")
private Integer creatorId;
/**
* 更新时间
*/
@TableField("update_time")
private LocalDateTime updateTime;
/**
* 是否删除0-未删除1-已删除)
*/
@TableField("is_deleted")
private Byte isDeleted;
/**
* 文件夹描述
*/
@TableField("description")
private String description;
}

View File

@@ -0,0 +1,98 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 文件信息表
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("biz_files")
public class BizFiles implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 文件ID
*/
@TableId(value = "file_id", type = IdType.AUTO)
private String fileId;
/**
* 文件名称(含扩展名)
*/
@TableField("file_name")
private String fileName;
/**
* 所属文件夹ID关联folders表
*/
@TableField("folder_id")
private String folderId;
/**
* 文件大小(字节)
*/
@TableField("file_size")
private Long fileSize;
/**
* 文件类型image/jpeg、application/pdf
*/
@TableField("file_type")
private String fileType;
/**
* 文件存储路径物理路径或云存储URL
*/
@TableField("file_path")
private String filePath;
/**
* 上传人ID关联用户表
*/
@TableField("creator_id")
private Integer creatorId;
/**
* 上传时间
*/
@TableField("upload_time")
private LocalDateTime uploadTime;
/**
* 更新时间(如修改名称)
*/
@TableField("update_time")
private LocalDateTime updateTime;
/**
* 是否删除0-未删除1-已删除)
*/
@TableField("is_deleted")
private Byte isDeleted;
/**
* 文件版本号(用于版本控制)
*/
@TableField("version")
private Integer version;
/**
* 文件MD5值用于去重校验
*/
@TableField("md5")
private String md5;
}

View File

@@ -0,0 +1,41 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author gaoxq
* @since 2025-11-14
*/
@Getter
@Setter
@TableName("biz_home_user")
public class BizHomeUser implements Serializable {
private static final long serialVersionUID = 1L;
@TableField("create_time")
private LocalDateTime createTime;
@TableId(value = "user_id", type = IdType.AUTO)
private String userId;
@TableField("user_name")
private String userName;
@TableField("password")
private String password;
@TableField("uname")
private String uname;
}

View File

@@ -0,0 +1,104 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 快捷登录系统信息表
* </p>
*
* @author gaoxq
* @since 2025-11-15
*/
@Getter
@Setter
@TableName("biz_quick_login")
public class BizQuickLogin implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 自增主键
*/
@TableId(value = "id", type = IdType.AUTO)
private String id;
/**
* 系统名称
*/
@TableField("system_name")
private String systemName;
/**
* 首页地址
*/
@TableField("homepage_url")
private String homepageUrl;
/**
* 图标类名(Font Awesome)
*/
@TableField("icon_class")
private String iconClass;
/**
* 图标颜色(关联Tailwind配置)
*/
@TableField("icon_color")
private String iconColor;
/**
* 排序序号(升序排列)
*/
@TableField("sort_order")
private Integer sortOrder;
/**
* 是否启用(1:启用 0:禁用)
*/
@TableField("is_enabled")
private Integer isEnabled;
/**
* 更新时间
*/
@TableField("update_time")
private LocalDateTime updateTime;
/**
* 租户id
*/
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
}

View File

@@ -0,0 +1,106 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 服务器信息表
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("biz_server_info")
public class BizServerInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 记录时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private String id;
/**
* 主机运行时间
*/
@TableField("uptime")
private String uptime;
/**
* 操作系统
*/
@TableField("os")
private String os;
/**
* 内核版本
*/
@TableField("kernel_version")
private String kernelVersion;
/**
* 主机名
*/
@TableField("hostname")
private String hostname;
/**
* IP地址
*/
@TableField("ip_address")
private String ipAddress;
/**
* CPU型号
*/
@TableField("cpu_model")
private String cpuModel;
/**
* 内存总量
*/
@TableField("memory_total")
private String memoryTotal;
/**
* CPU使用率(%)
*/
@TableField("cpu_usage")
private Double cpuUsage;
/**
* 内存使用率(%)
*/
@TableField("memory_usage")
private Double memoryUsage;
/**
* 最后一次检测到在线的时间
*/
@TableField("last_online_time")
private LocalDateTime lastOnlineTime;
/**
* 主机唯一标识
*/
@TableField("host_id")
private String hostId;
}

View File

@@ -0,0 +1,95 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 待办任务子表(关联主任务)
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("biz_sub_task")
public class BizSubTask implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 记录时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 唯一标识
*/
@TableId(value = "sub_task_id", type = IdType.AUTO)
private String subTaskId;
/**
* 关联的主任务ID外键
*/
@TableField("parent_task_id")
private String parentTaskId;
/**
* 子任务详明细
*/
@TableField("sub_task_name")
private String subTaskName;
/**
* 子任务优先级
*/
@TableField("priority")
private String priority;
/**
* 任务状态
*/
@TableField("ustatus")
private String ustatus;
/**
* 完成时间
*/
@TableField("finish_time")
private LocalDateTime finishTime;
@TableField("remark")
private String remark;
/**
* 租户id
*/
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
}

View File

@@ -0,0 +1,120 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* VIEW
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("biz_todo_task_view")
public class BizTodoTaskView implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 记录时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 唯一标识
*/
@TableField("task_id")
private String taskId;
/**
* 任务名称
*/
@TableField("task_name")
private String taskName;
/**
* 任务详细描述
*/
@TableField("task_desc")
private String taskDesc;
/**
* 任务截止时间
*/
@TableField("deadline")
private LocalDateTime deadline;
/**
* 待办人员
*/
@TableField("todo_user")
private String todoUser;
/**
* 创建人员
*/
@TableField("login_user")
private String loginUser;
/**
* 租户id
*/
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
/**
* 唯一标识
*/
@TableField("sub_task_id")
private String subTaskId;
/**
* 子任务详明细
*/
@TableField("sub_task_name")
private String subTaskName;
/**
* 子任务优先级
*/
@TableField("priority")
private String priority;
/**
* 任务状态
*/
@TableField("ustatus")
private String ustatus;
/**
* 完成时间
*/
@TableField("finish_time")
private LocalDateTime finishTime;
}

View File

@@ -0,0 +1,98 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 数据表字段信息表
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("data_table_field")
public class DataTableField implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 字段唯一标识(主键)
*/
@TableId(value = "field_id", type = IdType.AUTO)
private String fieldId;
/**
* 关联的数据表ID外键关联data_table_info.table_id
*/
@TableField("table_id")
private String tableId;
/**
* 字段序号(表示字段在表中的顺序)
*/
@TableField("field_order")
private Integer fieldOrder;
/**
* 字段类型int、varchar、datetime等
*/
@TableField("field_type")
private String fieldType;
/**
* 字段名称
*/
@TableField("field_name")
private String fieldName;
/**
* 字段长度如varchar(50)中的50数值型可表示精度
*/
@TableField("field_length")
private Integer fieldLength;
/**
* 字段说明
*/
@TableField("field_remark")
private String fieldRemark;
/**
* 租户id
*/
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
}

View File

@@ -0,0 +1,111 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 数据表基础信息表
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Getter
@Setter
@TableName("data_table_info")
public class DataTableInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 数据表唯一标识(主键)
*/
@TableId(value = "table_id", type = IdType.AUTO)
private String tableId;
/**
* 数据表名称
*/
@TableField("table_name")
private String tableName;
/**
* 数据表描述
*/
@TableField("table_comment")
private String tableComment;
/**
* 数据表大小单位MB
*/
@TableField("table_size")
private BigDecimal tableSize;
/**
* 数据来源(如:业务系统、文件导入等)
*/
@TableField("data_source")
private String dataSource;
/**
* 创建人
*/
@TableField("creator")
private String creator;
/**
* 记录条数
*/
@TableField("data_rows")
private Long dataRows;
/**
* 更新时间
*/
@TableField("update_time")
private LocalDateTime updateTime;
/**
* 租户id
*/
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
/**
* 备注信息
*/
@TableField("remarks")
private String remarks;
}

View File

@@ -2,6 +2,7 @@ package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
@@ -41,4 +42,18 @@ public class ErpSummaryAllView implements Serializable {
@TableField("f_cycle")
private String fCycle;
public BigDecimal getThisValue() {
return thisValue != null ? thisValue : BigDecimal.ZERO;
}
public BigDecimal getPrevValue() {
return prevValue != null ? prevValue : BigDecimal.ZERO;
}
public BigDecimal getMomRate() {
return momRate != null ? momRate : BigDecimal.ZERO;
}
}

View File

@@ -2,6 +2,7 @@ package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizDeviceInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 设备存储信息表 Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizDeviceInfoMapper extends BaseMapper<BizDeviceInfo> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizFileFolders;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 文件夹信息表 Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizFileFoldersMapper extends BaseMapper<BizFileFolders> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizFiles;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 文件信息表 Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizFilesMapper extends BaseMapper<BizFiles> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizHomeUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-14
*/
public interface BizHomeUserMapper extends BaseMapper<BizHomeUser> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizQuickLogin;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 快捷登录系统信息表 Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-15
*/
public interface BizQuickLoginMapper extends BaseMapper<BizQuickLogin> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizServerInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 服务器信息表 Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizServerInfoMapper extends BaseMapper<BizServerInfo> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizSubTask;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 待办任务子表(关联主任务) Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizSubTaskMapper extends BaseMapper<BizSubTask> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.BizTodoTaskView;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* VIEW Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizTodoTaskViewMapper extends BaseMapper<BizTodoTaskView> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.DataTableField;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 数据表字段信息表 Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface DataTableFieldMapper extends BaseMapper<DataTableField> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.DataTableInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 数据表基础信息表 Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface DataTableInfoMapper extends BaseMapper<DataTableInfo> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizDeviceInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 设备存储信息表 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizDeviceInfoService extends IService<BizDeviceInfo> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizFileFolders;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 文件夹信息表 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizFileFoldersService extends IService<BizFileFolders> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizFiles;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 文件信息表 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizFilesService extends IService<BizFiles> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizHomeUser;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-14
*/
public interface BizHomeUserService extends IService<BizHomeUser> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizQuickLogin;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 快捷登录系统信息表 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-15
*/
public interface BizQuickLoginService extends IService<BizQuickLogin> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizServerInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务器信息表 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizServerInfoService extends IService<BizServerInfo> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizSubTask;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 待办任务子表(关联主任务) 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizSubTaskService extends IService<BizSubTask> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.BizTodoTaskView;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* VIEW 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface BizTodoTaskViewService extends IService<BizTodoTaskView> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.DataTableField;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 数据表字段信息表 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface DataTableFieldService extends IService<DataTableField> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.DataTableInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 数据表基础信息表 服务类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
public interface DataTableInfoService extends IService<DataTableInfo> {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizDeviceInfo;
import com.mini.capi.biz.mapper.BizDeviceInfoMapper;
import com.mini.capi.biz.service.BizDeviceInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 设备存储信息表 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class BizDeviceInfoServiceImpl extends ServiceImpl<BizDeviceInfoMapper, BizDeviceInfo> implements BizDeviceInfoService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizFileFolders;
import com.mini.capi.biz.mapper.BizFileFoldersMapper;
import com.mini.capi.biz.service.BizFileFoldersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 文件夹信息表 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class BizFileFoldersServiceImpl extends ServiceImpl<BizFileFoldersMapper, BizFileFolders> implements BizFileFoldersService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizFiles;
import com.mini.capi.biz.mapper.BizFilesMapper;
import com.mini.capi.biz.service.BizFilesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 文件信息表 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class BizFilesServiceImpl extends ServiceImpl<BizFilesMapper, BizFiles> implements BizFilesService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizHomeUser;
import com.mini.capi.biz.mapper.BizHomeUserMapper;
import com.mini.capi.biz.service.BizHomeUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-14
*/
@Service
public class BizHomeUserServiceImpl extends ServiceImpl<BizHomeUserMapper, BizHomeUser> implements BizHomeUserService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizQuickLogin;
import com.mini.capi.biz.mapper.BizQuickLoginMapper;
import com.mini.capi.biz.service.BizQuickLoginService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 快捷登录系统信息表 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-15
*/
@Service
public class BizQuickLoginServiceImpl extends ServiceImpl<BizQuickLoginMapper, BizQuickLogin> implements BizQuickLoginService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizServerInfo;
import com.mini.capi.biz.mapper.BizServerInfoMapper;
import com.mini.capi.biz.service.BizServerInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务器信息表 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class BizServerInfoServiceImpl extends ServiceImpl<BizServerInfoMapper, BizServerInfo> implements BizServerInfoService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizSubTask;
import com.mini.capi.biz.mapper.BizSubTaskMapper;
import com.mini.capi.biz.service.BizSubTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 待办任务子表(关联主任务) 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class BizSubTaskServiceImpl extends ServiceImpl<BizSubTaskMapper, BizSubTask> implements BizSubTaskService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.BizTodoTaskView;
import com.mini.capi.biz.mapper.BizTodoTaskViewMapper;
import com.mini.capi.biz.service.BizTodoTaskViewService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* VIEW 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class BizTodoTaskViewServiceImpl extends ServiceImpl<BizTodoTaskViewMapper, BizTodoTaskView> implements BizTodoTaskViewService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.DataTableField;
import com.mini.capi.biz.mapper.DataTableFieldMapper;
import com.mini.capi.biz.service.DataTableFieldService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 数据表字段信息表 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class DataTableFieldServiceImpl extends ServiceImpl<DataTableFieldMapper, DataTableField> implements DataTableFieldService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.DataTableInfo;
import com.mini.capi.biz.mapper.DataTableInfoMapper;
import com.mini.capi.biz.service.DataTableInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 数据表基础信息表 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-11-16
*/
@Service
public class DataTableInfoServiceImpl extends ServiceImpl<DataTableInfoMapper, DataTableInfo> implements DataTableInfoService {
}

View File

@@ -0,0 +1,155 @@
package com.mini.capi.biz;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mini.capi.api.sys.sysService;
import com.mini.capi.biz.domain.*;
import com.mini.capi.biz.service.*;
import com.mini.capi.model.info.CpuInfo;
import com.mini.capi.model.info.DiskInfo;
import com.mini.capi.model.info.RunInfo;
import com.mini.capi.model.info.ServerInfo;
import com.mini.capi.utils.SqlUtils;
import com.mini.capi.utils.SystemInfoUtil;
import com.mini.capi.utils.vDate;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@Controller
public class viewController {
@Resource
private BizMonitorHostService hostService;
@Resource
private BizQuickLoginService loginService;
@Resource
private BizFilesService filesService;
@Resource
private BizFileFoldersService foldersService;
@Resource
private sysService service;
@Resource
private BizServerInfoService bizServerInfoService;
@Resource
private BizDeviceInfoService bizDeviceInfoService;
@Resource
private DataTableInfoService dataTableInfoService;
@Resource
private DataTableFieldService dataTableFieldService;
@Resource
private BizTodoTaskViewService bizTodoTaskViewService;
@GetMapping("/login")
public String showLoginPage() {
return "login";
}
@GetMapping("/swagger")
public String redirectToSwagger() {
return "redirect:/swagger-ui/index.html";
}
@GetMapping("/biz/index")
public String getUserHome(Model model, HttpSession session) throws Exception {
RunInfo runInfo = service.getRunInfo();
List<BizMonitorHost> hosts = hostService.list();
List<BizQuickLogin> storages = loginService.list();
BizHomeUser user = (BizHomeUser) session.getAttribute("currentUser");
QueryWrapper<BizTodoTaskView> taskViewQueryWrapper = new QueryWrapper<>();
taskViewQueryWrapper.notIn("ustatus", "CPT");
List<BizTodoTaskView> todoViews = bizTodoTaskViewService.list(taskViewQueryWrapper);
model.addAttribute("hosts", hosts);
model.addAttribute("storages", storages);
model.addAttribute("uname", user.getUname());
model.addAttribute("todoViews", todoViews);
model.addAttribute("times", vDate.getRunTimes(runInfo.getProcessInfo().getUptime()));
return "index";
}
@GetMapping("/biz/getServerInfo")
public String getServerInfo(Model model, String hostId) {
// 1. 查询服务器信息确保不为null
QueryWrapper<BizServerInfo> infoQueryWrapper = new QueryWrapper<>();
infoQueryWrapper.eq("host_id", hostId);
BizServerInfo info = bizServerInfoService.getOne(infoQueryWrapper);
// 若查询不到数据创建空对象避免前端null指针
model.addAttribute("info", info != null ? info : new BizServerInfo());
// 2. 查询设备列表,确保集合始终存在
QueryWrapper<BizDeviceInfo> deviceQueryWrapper = new QueryWrapper<>();
deviceQueryWrapper.eq("host_id", hostId);
List<BizDeviceInfo> devices = bizDeviceInfoService.list(deviceQueryWrapper);
// 若查询不到数据返回空集合而非null
model.addAttribute("devices", devices != null ? devices : Collections.emptyList());
return "server";
}
@GetMapping("/biz/getFieldDetail")
public String getFieldDetail(Model model, String tableId) {
DataTableInfo tableInfo = dataTableInfoService.getById(tableId);
QueryWrapper<DataTableField> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("table_id", tableId);
queryWrapper.orderByAsc("field_order");
List<DataTableField> fields = dataTableFieldService.list(queryWrapper);
String createSql = SqlUtils.CreateTableSql(tableInfo, fields);
String selectSql = SqlUtils.SelectSqlComments(tableInfo, fields);
model.addAttribute("createSql", createSql != null ? createSql : null);
model.addAttribute("selectSql", selectSql != null ? selectSql : null);
model.addAttribute("tableInfo", tableInfo != null ? tableInfo : new DataTableInfo());
model.addAttribute("fields", fields != null ? fields : Collections.emptyList());
return "field";
}
/**
* 数据地图
*/
@GetMapping("/biz/dataMap")
public String getDataMap(Model model) {
List<DataTableInfo> tables = dataTableInfoService.list();
Collections.sort(tables,
Comparator.nullsLast(Comparator.comparing(DataTableInfo::getCreateTime)).reversed()
);
model.addAttribute("tables", tables);
return "data";
}
/**
* 文档中心
*/
@GetMapping("/biz/dataDoc")
public String getDataDox(Model model) {
List<BizFiles> files = filesService.list();
List<BizFileFolders> folders = foldersService.list();
model.addAttribute("files", files);
model.addAttribute("folders", folders);
return "file";
}
}

View File

@@ -0,0 +1,48 @@
package com.mini.capi.biz;
import com.mini.capi.biz.domain.BizSubTask;
import com.mini.capi.biz.service.BizSubTaskService;
import com.mini.capi.model.info.TodoHandleDTO;
import jakarta.annotation.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/biz")
public class workController {
@Resource
private BizSubTaskService bizSubTaskService;
/**
* 完成待办
*
* @return
*/
@PostMapping("/finishTodoSub")
public ResponseEntity<Void> finishTodoSub(@RequestBody TodoHandleDTO handleDTO) {
// 验证参数
if (handleDTO.getTaskId() == null || handleDTO.getOpinion() == null || handleDTO.getOpinion().trim().isEmpty()) {
return ResponseEntity.badRequest().build();
}
try {
// 调用服务层处理任务
BizSubTask bizSubTask = bizSubTaskService.getById(handleDTO.getTaskId());
bizSubTask.setUstatus("CPT");
bizSubTask.setFinishTime(LocalDateTime.now());
bizSubTask.setRemark(handleDTO.getOpinion());
bizSubTaskService.updateById(bizSubTask);
return ResponseEntity.ok().build();
} catch (Exception e) {
// 处理异常(如任务不存在、数据库错误等)
return ResponseEntity.status(500).build();
}
}
}

View File

@@ -0,0 +1,23 @@
package com.mini.capi.config;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String cPath = request.getContextPath();
HttpSession session = request.getSession();
Object currentUser = session.getAttribute("currentUser");
if (currentUser != null) {
return true;
} else {
response.sendRedirect(cPath + "/login");
return false; // 拦截
}
}
}

View File

@@ -1,14 +1,33 @@
package com.mini.capi.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer{
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 访问根路径 "/" 时,自动重定向到 Swagger UI
registry.addRedirectViewController("/", "/login");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册登录拦截器
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 拦截所有路径
.excludePathPatterns( // 排除不需要拦截的路径
"/", // 登录页
"/login", // 登录页
"/biz/userLogin", // 登录接口
"/static/**", // 静态资源CSS、JS、图片等
"/erpApi/**",
"/appApi/**",
"/jobApi/**"
);
}
}

View File

@@ -0,0 +1,13 @@
package com.mini.capi.model.auth;
import lombok.Data;
import java.io.Serializable;
@Data
public class LoginRequest implements Serializable {
private String username;
private String password;
private boolean remember;
}

View File

@@ -0,0 +1,22 @@
package com.mini.capi.model.info;
import lombok.Data;
import java.io.Serializable;
@Data
public class CpuInfo implements Serializable {
private double cpuUsage; // CPU使用率
private double memoryUsage; // 内存使用率
public CpuInfo() {
}
public CpuInfo(double cpuUsage, double memoryUsage) {
this.cpuUsage = cpuUsage;
this.memoryUsage = memoryUsage;
}
}

View File

@@ -0,0 +1,26 @@
package com.mini.capi.model.info;
import lombok.Data;
import java.io.Serializable;
@Data
public class DiskInfo implements Serializable {
private String device; // 设备
private String mountPoint; // 挂载点
private String totalSize; // 总容量
private String usedSize; // 已使用
private double usageRate; // 使用率
public DiskInfo() {
}
public DiskInfo(String device, String mountPoint, String totalSize, String usedSize, double usageRate) {
this.device = device;
this.mountPoint = mountPoint;
this.totalSize = totalSize;
this.usedSize = usedSize;
this.usageRate = usageRate;
}
}

View File

@@ -0,0 +1,19 @@
package com.mini.capi.model.info;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class FileInfo implements Serializable {
private String id; // 文件唯一标识
private String name; // 文件名
private String type; // 文件类型pdf、excel、image等
private String size; // 文件大小
private String source; // 文件来源(本地上传、共享文件等)
private LocalDateTime createTime; // 创建时间
private String creator; // 创建人
private String folderId; // 所属文件夹ID
}

View File

@@ -0,0 +1,30 @@
package com.mini.capi.model.info;
import lombok.Data;
import java.io.Serializable;
@Data
public class ServerInfo implements Serializable {
private String uptime; // 主机运行时间
private String os; // 操作系统
private String kernelVersion; // 内核版本
private String hostname; // 主机名
private String ipAddress; // IP地址
private String cpuModel; // CPU型号
private String memoryTotal; // 内存总量
public ServerInfo() {
}
public ServerInfo(String uptime, String os, String kernelVersion, String hostname, String ipAddress, String cpuModel, String memoryTotal) {
this.uptime = uptime;
this.os = os;
this.kernelVersion = kernelVersion;
this.hostname = hostname;
this.ipAddress = ipAddress;
this.cpuModel = cpuModel;
this.memoryTotal = memoryTotal;
}
}

View File

@@ -0,0 +1,15 @@
package com.mini.capi.model.info;
import lombok.Data;
import java.io.Serializable;
@Data
public class TodoHandleDTO implements Serializable {
private Long taskId;
private String opinion;
// 必须有默认无参构造函数
public TodoHandleDTO() {}
}

View File

@@ -29,7 +29,7 @@ public class demo {
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
})
.strategyConfig(builder -> {
builder.addInclude("biz_cities,biz_company,biz_mail_account,biz_project_info,biz_project_requirements,biz_province,biz_resume_employee,biz_website_storage,biz_municipalities,biz_monitor_host,biz_monitor_account,erp_summary_all_view,erp_account,erp_transaction_flow,erp_expense,erp_category,erp_income,erp_summary_source_view,biz_project_report,biz_mail_sent")
builder.addInclude("biz_sub_task")
.addTablePrefix("biz_,erp_")
.entityBuilder()
.enableLombok()

View File

@@ -150,4 +150,57 @@ public class FileUtils {
}
return result;
}
public static String getFileType(String fileName) {
if (fileName == null || fileName.isEmpty()) {
return "unknown";
}
String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
switch (extension) {
case "pdf":
return "pdf";
case "doc":
case "docx":
return "word";
case "xls":
case "xlsx":
return "excel";
case "ppt":
case "pptx":
return "ppt";
case "jpg":
case "jpeg":
case "png":
case "gif":
return "image";
case "mp4":
case "avi":
case "mov":
return "video";
case "mp3":
case "wav":
return "audio";
default:
// 如果没有扩展名,视为文件夹
if (!fileName.contains(".")) {
return "folder";
}
return "unknown";
}
}
// 格式化文件大小(字节转人类可读格式)
public static String formatFileSize(long bytes) {
if (bytes < 1024) {
return bytes + " B";
} else if (bytes < 1024 * 1024) {
return String.format("%.1f KB", bytes / 1024.0);
} else if (bytes < 1024 * 1024 * 1024) {
return String.format("%.1f MB", bytes / (1024.0 * 1024));
} else {
return String.format("%.1f GB", bytes / (1024.0 * 1024 * 1024));
}
}
}

View File

@@ -1,132 +0,0 @@
package com.mini.capi.utils;
import org.springframework.util.StringUtils;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class MailParseUtils {
/**
* 解析邮件发件人(名称+地址)
*/
public static String parseFrom(Message message) throws MessagingException {
Address[] froms = message.getFrom();
if (froms == null || froms.length == 0) {
return "";
}
InternetAddress from = (InternetAddress) froms[0];
String fromName = from.getPersonal(); // 发件人名称可能为null
String fromAddr = from.getAddress(); // 发件人地址
return StringUtils.hasText(fromName) ? fromName + "<" + fromAddr + ">" : fromAddr;
}
/**
* 解析邮件收件人(多个用逗号分隔)
*/
public static String parseTo(Message message) throws MessagingException {
return parseRecipients(message, Message.RecipientType.TO);
}
/**
* 解析邮件抄送人(多个用逗号分隔)
*/
public static String parseCc(Message message) throws MessagingException {
return parseRecipients(message, Message.RecipientType.CC);
}
/**
* 通用解析收件人/抄送人
*/
private static String parseRecipients(Message message, Message.RecipientType type) throws MessagingException {
Address[] recipients = message.getRecipients(type);
if (recipients == null || recipients.length == 0) {
return "";
}
List<String> addrList = new ArrayList<>();
for (Address addr : recipients) {
InternetAddress internetAddr = (InternetAddress) addr;
String name = internetAddr.getPersonal();
String address = internetAddr.getAddress();
addrList.add(StringUtils.hasText(name) ? name + "<" + address + ">" : address);
}
return String.join(",", addrList);
}
/**
* 解析邮件内容(支持文本/HTML
*/
public static String parseContent(Part part) throws MessagingException, IOException {
if (part.isMimeType("text/plain") || part.isMimeType("text/html")) {
// 文本/HTML直接读取
return (String) part.getContent();
}
// 多部分内容(含附件),递归解析文本部分
if (part.isMimeType("multipart/*")) {
MimeMultipart multipart = (MimeMultipart) part.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
String content = parseContent(bodyPart);
if (StringUtils.hasText(content)) {
return content;
}
}
}
return "";
}
/**
* 提取邮件附件(返回附件流+原始文件名)
*/
public static List<AttachmentInfo> extractAttachments(Part part) throws MessagingException, IOException {
List<AttachmentInfo> attachments = new ArrayList<>();
// 多部分内容才可能有附件
if (part.isMimeType("multipart/*")) {
MimeMultipart multipart = (MimeMultipart) part.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
// 判断是否为附件Disposition为ATTACHMENT或INLINE
String disposition = bodyPart.getDisposition();
if (disposition != null && (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE))) {
// 获取原始文件名(处理中文乱码)
String originalFileName = MimeUtility.decodeText(bodyPart.getFileName());
// 获取附件输入流
InputStream inputStream = bodyPart.getInputStream();
attachments.add(new AttachmentInfo(originalFileName, inputStream));
} else {
// 递归处理嵌套的多部分内容
attachments.addAll(extractAttachments(bodyPart));
}
}
}
return attachments;
}
/**
* 附件信息封装(原始文件名+输入流)
*/
public static class AttachmentInfo {
private String originalFileName;
private InputStream inputStream;
public AttachmentInfo(String originalFileName, InputStream inputStream) {
this.originalFileName = originalFileName;
this.inputStream = inputStream;
}
// Getter
public String getOriginalFileName() {
return originalFileName;
}
public InputStream getInputStream() {
return inputStream;
}
}
}

View File

@@ -1,88 +0,0 @@
package com.mini.capi.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
public class MailUtil {
private static final Logger logger = LoggerFactory.getLogger(MailUtil.class);
/**
* 获取邮件内容
*/
public static String getEmailContent(Message message) {
try {
Object content = message.getContent();
// 简单文本内容
if (content instanceof String) {
return (String) content;
}
// 复杂内容(多部分)
else if (content instanceof Multipart) {
Multipart multipart = (Multipart) content;
StringBuilder contentBuilder = new StringBuilder();
// 遍历所有部分
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
// 忽略附件
if (BodyPart.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) ||
bodyPart.getFileName() != null) {
continue;
}
// 获取内容
Object partContent = bodyPart.getContent();
if (partContent instanceof String) {
contentBuilder.append(partContent);
} else if (partContent instanceof Multipart) {
// 处理嵌套的多部分内容
contentBuilder.append(getMultipartContent((Multipart) partContent));
}
}
return contentBuilder.toString();
}
} catch (Exception e) {
logger.error("获取邮件内容失败", e);
}
return "";
}
/**
* 处理嵌套的多部分内容
*/
private static String getMultipartContent(Multipart multipart) throws MessagingException, IOException {
StringBuilder contentBuilder = new StringBuilder();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
// 忽略附件
if (BodyPart.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) ||
bodyPart.getFileName() != null) {
continue;
}
Object partContent = bodyPart.getContent();
if (partContent instanceof String) {
contentBuilder.append(partContent);
} else if (partContent instanceof Multipart) {
contentBuilder.append(getMultipartContent((Multipart) partContent));
}
}
return contentBuilder.toString();
}
}

View File

@@ -0,0 +1,98 @@
package com.mini.capi.utils;
import com.mini.capi.biz.domain.DataTableField;
import com.mini.capi.biz.domain.DataTableInfo;
import java.util.List;
public class SqlUtils {
/**
* 生成CREATE TABLE语句
*
* @param tableInfo 数据表基础信息
* @param fieldList 字段列表
* @return CREATE TABLE语句
*/
public static String CreateTableSql(DataTableInfo tableInfo, List<DataTableField> fieldList) {
StringBuilder sb = new StringBuilder();
// 表定义开始
sb.append("CREATE TABLE ").append(tableInfo.getTableName()).append(" (\n");
// 拼接字段定义
for (int i = 0; i < fieldList.size(); i++) {
DataTableField field = fieldList.get(i);
sb.append(" ").append(field.getFieldName()).append(" ");
// 处理字段类型和长度
if (field.getFieldLength() != null && field.getFieldLength() > 0) {
sb.append(field.getFieldType()).append("(").append(field.getFieldLength()).append(") ");
} else {
sb.append(field.getFieldType()).append(" ");
}
// 处理主键简单判断fieldId为主键字段
if ("field_id".equals(field.getFieldName()) || "table_id".equals(field.getFieldName())) {
sb.append("NOT NULL AUTO_INCREMENT ");
} else {
sb.append("DEFAULT NULL ");
}
// 字段注释
if (field.getFieldRemark() != null && !field.getFieldRemark().isEmpty()) {
sb.append("COMMENT '").append(field.getFieldRemark()).append("'");
}
// 最后一个字段不加逗号
if (i != fieldList.size() - 1) {
sb.append(",");
}
sb.append("\n");
}
// 表引擎和字符集
sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ");
// 表注释
if (tableInfo.getTableComment() != null && !tableInfo.getTableComment().isEmpty()) {
sb.append("COMMENT\t'").append(tableInfo.getTableComment()).append("'");
}
sb.append(";");
return sb.toString();
}
/**
* 生成带注释的SELECT语句
*
* @param tableInfo 数据表基础信息
* @param fieldList 字段列表
* @return 带注释的SELECT语句
*/
public static String SelectSqlComments(DataTableInfo tableInfo, List<DataTableField> fieldList) {
StringBuilder sb = new StringBuilder();
// 表注释
sb.append("-- 表名:").append(tableInfo.getTableName()).append("\n");
sb.append("-- 描述:").append(tableInfo.getTableComment() != null ? tableInfo.getTableComment() : "").append("\n");
sb.append("-- 数据来源:").append(tableInfo.getDataSource() != null ? tableInfo.getDataSource() : "未知").append("\n");
// SELECT语句开始
sb.append("SELECT\n");
// 拼接字段(带注释)
for (int i = 0; i < fieldList.size(); i++) {
DataTableField field = fieldList.get(i);
sb.append(" ").append(field.getFieldName()).append("");
// 字段注释
if (field.getFieldRemark() != null && !field.getFieldRemark().isEmpty()) {
sb.append(" -- ").append(field.getFieldRemark());
}
// 最后一个字段不加逗号
if (i != fieldList.size() - 1) {
sb.append(",");
}
sb.append("\n");
}
// 表名
sb.append("FROM ").append(tableInfo.getTableName()).append(";");
return sb.toString();
}
}

View File

@@ -0,0 +1,183 @@
package com.mini.capi.utils;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.mini.capi.model.info.CpuInfo;
import com.mini.capi.model.info.DiskInfo;
import com.mini.capi.model.info.ServerInfo;
import lombok.Data;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class SystemInfoUtil {
// SSH 连接超时时间(毫秒)
private static final int SSH_TIMEOUT = 5000;
/**
* 建立SSH连接
*/
private static Session getSshSession(String host, int port, String username, String password) throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, host, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(SSH_TIMEOUT);
session.connect();
return session;
}
/**
* 执行SSH命令并返回结果
*/
private static String executeCommand(Session session, String command) throws Exception {
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
InputStream in = channel.getInputStream();
channel.connect();
BufferedReader reader = new BufferedReader(
new InputStreamReader(in, StandardCharsets.UTF_8)
);
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line).append("\n");
}
reader.close();
channel.disconnect();
return result.toString().trim();
}
/**
* 获取服务器基础信息
*/
public static ServerInfo getServerBasicInfo(String host, int port, String username, String password, String ipAddress) throws Exception {
ServerInfo info = new ServerInfo();
Session session = null;
try {
session = getSshSession(host, port, username, password);
// 主机运行时间
String uptimeResult = executeCommand(session, "uptime");
if (StringUtils.hasText(uptimeResult)) {
String[] parts = uptimeResult.split("up ");
if (parts.length > 1) {
info.setUptime(parts[1].split(", ")[0]);
}
}
// 操作系统
String osResult = executeCommand(session, "cat /etc/os-release | grep PRETTY_NAME | cut -d'=' -f2 | tr -d '\"'");
info.setOs(osResult.isEmpty() ? "Unknown" : osResult);
// 内核版本
info.setKernelVersion(executeCommand(session, "uname -r"));
// 主机名
info.setHostname(executeCommand(session, "hostname"));
// IP地址传入参数
info.setIpAddress(ipAddress);
// CPU型号
String cpuResult = executeCommand(session, "cat /proc/cpuinfo | grep 'model name' | head -n 1 | cut -d: -f2 | sed -e 's/^ *//'");
info.setCpuModel(cpuResult.isEmpty() ? "Unknown" : cpuResult);
// 内存总量
String memResult = executeCommand(session, "free -h | grep Mem | awk '{print $2}'");
info.setMemoryTotal(memResult.isEmpty() ? "Unknown" : memResult);
} finally {
if (session != null && session.isConnected()) {
session.disconnect();
}
}
return info;
}
/**
* 获取CPU和内存使用率
*/
public static CpuInfo getCpuMemUsage(String host, int port, String username, String password) throws Exception {
CpuInfo usage = new CpuInfo();
Session session = null;
try {
session = getSshSession(host, port, username, password);
// CPU使用率
String cpuCommand = "top -bn2 | grep '%Cpu' | tail -n1 | awk '{print 100 - $8}'";
String cpuResult = executeCommand(session, cpuCommand);
if (StringUtils.hasText(cpuResult)) {
usage.setCpuUsage(Double.parseDouble(cpuResult));
}
// 内存使用率
String memCommand = "free | grep Mem | awk '{print $3/$2 * 100}'";
String memResult = executeCommand(session, memCommand);
if (StringUtils.hasText(memResult)) {
usage.setMemoryUsage(Double.parseDouble(memResult));
}
} finally {
if (session != null && session.isConnected()) {
session.disconnect();
}
}
return usage;
}
/**
* 获取所有磁盘信息
*/
public static List<DiskInfo> getDiskInfos(String host, int port, String username, String password) throws Exception {
List<DiskInfo> diskInfos = new ArrayList<>();
Session session = null;
try {
session = getSshSession(host, port, username, password);
// 关键修改:强制英文输出 + 调整字段索引
String diskCommand = "LANG=en_US.UTF-8 df -h | awk '{print $1, $6, $2, $3, $5}'";
String diskResult = executeCommand(session, diskCommand);
if (StringUtils.hasText(diskResult)) {
String[] lines = diskResult.split("\n");
for (String line : lines) {
// 过滤空行和标题行
if (line.trim().isEmpty() || line.contains("Filesystem")) {
continue;
}
// 按任意空格分割(兼容多个空格)
String[] parts = line.trim().split("\\s+");
if (parts.length >= 5) {
String usageStr = parts[4].replace("%", "").trim();
DiskInfo diskInfo = new DiskInfo(parts[0], parts[1], parts[2], parts[3], Double.parseDouble(usageStr));
diskInfos.add(diskInfo);
}
}
}
} finally {
if (session != null && session.isConnected()) {
session.disconnect();
}
}
return diskInfos;
}
}

View File

@@ -46,4 +46,39 @@ public class vDate {
return getNow();
}
}
public static String getRunTimes(long totalSeconds) {
if (totalSeconds < 0) {
throw new IllegalArgumentException("输入的秒数不能为负数");
}
// 定义时间单位换算关系
long secondsPerMinute = 60;
long secondsPerHour = secondsPerMinute * 60; // 3600秒/小时
long secondsPerDay = secondsPerHour * 24; // 86400秒/天
// 计算各单位数值
long days = totalSeconds / secondsPerDay;
long remainingSecondsAfterDays = totalSeconds % secondsPerDay;
long hours = remainingSecondsAfterDays / secondsPerHour;
long remainingSecondsAfterHours = remainingSecondsAfterDays % secondsPerHour;
long minutes = remainingSecondsAfterHours / secondsPerMinute;
long seconds = remainingSecondsAfterHours % secondsPerMinute;
// 拼接结果字符串
StringBuilder result = new StringBuilder();
if (days > 0) {
result.append(days).append("");
}
if (hours > 0) {
result.append(hours).append("小时");
}
if (minutes > 0) {
result.append(minutes).append("");
}
// 确保至少显示秒数即使其他单位都为0
result.append(seconds).append("");
return result.toString();
}
}