初始化前端目录

This commit is contained in:
2025-09-03 21:42:51 +08:00
parent de83878345
commit 31ebed0b5e
68 changed files with 4230 additions and 3461 deletions

View File

@@ -14,12 +14,12 @@ public class AuthInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// HttpSession session = request.getSession();
// ApiUser apiUser = (ApiUser) session.getAttribute("Authorization");
// if (apiUser == null) {
// response.sendRedirect(request.getContextPath() + "/login");
// return false;
// }
HttpSession session = request.getSession();
ApiUser apiUser = (ApiUser) session.getAttribute("userInfo");
if (apiUser == null) {
response.sendRedirect(request.getContextPath() + "/login");
return false;
}
return true;
}
}

View File

@@ -1,11 +1,17 @@
package com.mini.capi.config;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;
import java.io.IOException;
@Configuration
@RequiredArgsConstructor
@@ -13,35 +19,51 @@ public class WebMvcConfig implements WebMvcConfigurer {
private final AuthInterceptor authInterceptor;
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/cApi/**")
// .addResourceLocations("classpath:/static/")
// .setCachePeriod(0);
// }
//
//
// @Override
// public void addViewControllers(ViewControllerRegistry registry) {
// registry.addViewController("/cApi/**")
// .setViewName("forward:/cApi/index.html");
// }
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("forward:/index.html");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
Resource requested = super.getResource(resourcePath, location);
// 文件存在就返回,不存在返回 index.html
return requested != null ? requested : new ClassPathResource("/static/index.html");
}
});
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**") // 需要拦截的路径
.excludePathPatterns( // 排除的路径
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns(
// ① 排除 Vue 静态资源(匹配 static 目录下所有 js/css/img 等)
"/js/**",
"/css/**",
"/img/**",
"/favicon.ico",
"/index.html", // 排除首页Vue 入口)
"/assets/**", // 若 Vue 打包后有 assets 目录,需排除
"/resource/**", // 若有其他静态资源目录,需排除
"/cApi/index/**",
"/login",
"/index.html",
"/assets/**",
"/resource/**",
"/swagger-ui/**",
"/v3/api-docs/**",
"/Sys/jobs/**",
"/Sys/login/**", // 你的登录接口(原 /Sys/login/** 缺少 /cApi 前缀,修复)
"/Sys/jobs/**", // 原路径补充 /cApi 前缀
"/Sys/hosts/**",
"/Sys/dbs/**",
"/Sys/login/**"
"/cApi/swagger-ui/**",
"/cApi/v3/api-docs/**"
);
}
}
}

View File

@@ -1,50 +0,0 @@
package com.mini.capi.job;
import com.mini.capi.model.ApiResult;
import com.mini.capi.sys.service.DbService;
import com.mini.capi.sys.service.DockerService;
import com.mini.capi.utils.*;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Sys/jobs")
public class taskEnable {
@Resource
private DockerService dockerService;
@Resource
private DbService dbService;
/**
* 获取容器主机的磁盘使用情况
*/
@GetMapping("/getTaskDockerDiskInfo")
public ApiResult<?> jobHostDisk(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dockerService.jobHostDisk();
}
/**
* 运行全部任务数据同步
*/
@GetMapping("/getTaskSyncDbInfo")
public ApiResult<?> jobSyncAllTask(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dbService.jobSyncAllTask();
}
}

View File

@@ -1,9 +1,11 @@
package com.mini.capi.model;
import com.mini.capi.biz.domain.SyncTablesView;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
@Data
public class ApiResult<T> implements Serializable {
@@ -37,6 +39,7 @@ public class ApiResult<T> implements Serializable {
this.result = data;
}
/* ---------------- 静态工厂方法 ---------------- */
/**

View File

@@ -0,0 +1,124 @@
package com.mini.capi.sys.Api;
import com.mini.capi.model.ApiResult;
import com.mini.capi.model.TabResult;
import com.mini.capi.sys.service.DbService;
import com.mini.capi.sys.service.DockerService;
import com.mini.capi.sys.service.HostService;
import com.mini.capi.utils.vToken;
import jakarta.annotation.Resource;
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("/Sys/api")
public class apiController {
@Resource
private DbService dbService;
@Resource
private HostService hostService;
@Resource
private DockerService dockerService;
/**
* 获取MySQL的当前连接下的所有数据表
*/
@GetMapping("/getApiSourceTables")
public ApiResult<List<TabResult>> listSourceTables(String token, String dbId) {
// 1. 验证token有效性
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dbService.listSourceTables(dbId);
}
@GetMapping("/getApiInfo")
public ApiResult<List<HostService.SnapshotDTO>> getApiInfo(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.getApiInfo();
}
/**
* 获取容器列表
*/
@GetMapping("/getApiDockerInfo")
public ApiResult<?> getDockerInfo(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.getDockerInfo();
}
/**
* 启动容器
*/
@GetMapping("/getApiStartDockerInfo")
public ApiResult<?> startDockerInfo(String id, String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.startDockerInfo(id);
}
/**
* 停止容器
*/
@GetMapping("/getApiStopDockerInfo")
public ApiResult<?> stopDockerInfo(String id, String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.stopDockerInfo(id);
}
/**
* 获取容器主机的磁盘使用情况
*/
@GetMapping("/getTaskDockerDiskInfo")
public ApiResult<?> jobHostDisk(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dockerService.jobHostDisk();
}
/**
* 运行全部任务数据同步
*/
@GetMapping("/getTaskSyncDbInfo")
public ApiResult<?> jobSyncAllTask(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dbService.jobSyncAllTask();
}
/**
* 运行单个任务
*/
@GetMapping("/getTaskSyncDbByInfo")
public ApiResult<?> jobSyncOneTask(String token, String taskId) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dbService.jobSyncOneTask(taskId);
}
}

View File

@@ -1,23 +1,32 @@
package com.mini.capi.sys.controller;
package com.mini.capi.sys.App;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mini.capi.biz.domain.DbConfig;
import com.mini.capi.biz.domain.SyncTablesView;
import com.mini.capi.biz.domain.SyncTask;
import com.mini.capi.biz.service.DbConfigService;
import com.mini.capi.biz.service.SyncTablesViewService;
import com.mini.capi.biz.service.SyncTaskService;
import com.mini.capi.config.DataSourceConfig;
import com.mini.capi.model.ApiResult;
import com.mini.capi.sys.domain.SelectOption;
import jakarta.annotation.Resource;
import lombok.Data;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.Serializable;
import java.util.Collections;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@Controller
@RestController
@RequestMapping("/Sys/data")
public class dataController {
@@ -26,12 +35,11 @@ public class dataController {
@Resource
private DbConfigService dbConfigService;
private DbConfigService configService;
@GetMapping("/Sys/data/list")
public String listPage() {
return "views/data/list";
}
@Resource
private SyncTablesViewService tablesViewService;
@Data
@@ -73,6 +81,28 @@ public class dataController {
}
@Data
static class TableInfo implements Serializable {
private TabDetail tabDetail;
private List<TabColumns> tabColumns;
private long pkCnt;
private long idxCnt;
private long colCnt;
private String ddlSql;
private String selectSql;
public TableInfo(TabDetail tabDetail, List<TabColumns> tabColumns, long pkCnt, long idxCnt, long colCnt, String ddlSql, String selectSql) {
this.tabDetail = tabDetail;
this.tabColumns = tabColumns;
this.pkCnt = pkCnt;
this.idxCnt = idxCnt;
this.colCnt = colCnt;
this.ddlSql = ddlSql;
this.selectSql = selectSql;
}
}
public static String buildSelect(List<TabColumns> columns, TabDetail table) {
if (columns == null || columns.isEmpty() || table == null) {
return "-- no columns or table info";
@@ -160,18 +190,78 @@ public class dataController {
}
@GetMapping("/Sys/data/getTableDetail")
public String getTableDetail(String taskId, Model model) {
SyncTask task = syncTaskService.getById(taskId);
DbConfig dbConfig = dbConfigService.getById(task.getSourceDbId());
List<TabDetail> data;
List<TabColumns> columns;
/**
* 获取数据配置表
*
* @return
*/
@GetMapping("/getDbList")
public ApiResult<List<SelectOption>> getDbList() {
try {
JdbcTemplate jdbcTemplate = DataSourceConfig.createJdbcTemplate(dbConfig);
// 补充参数传递
String querySql = "SELECT CREATE_TIME,TABLE_NAME,TABLE_COMMENT,MAX_DATA_LENGTH,UPDATE_TIME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?";
List<DbConfig> configs = configService.list();
List<SelectOption> selectOptions = configs.stream()
.map(config -> new SelectOption(
config.getDbId(), // 下拉框value绑定值
config.getDbName(), // 下拉框label显示文本
false // 关键注释说明禁用原因所有数据库默认禁用选择需申请后启用
))
.collect(Collectors.toList());
return ApiResult.success(selectOptions);
} catch (Exception e) {
return ApiResult.error(401, e.getMessage());
}
}
/**
* 获取数据字段表
*
* @return
*/
@GetMapping("/getTableList")
public ApiResult<List<SyncTablesView>> getTableList(String dbId, String targetTable) {
try {
List<SyncTablesView> tablesViews = tablesViewService.list(
new QueryWrapper<SyncTablesView>()
.eq(StringUtils.hasText(dbId), "db_id", dbId)
.and(StringUtils.hasText(targetTable),
w -> w.like("target_table", targetTable)
.or()
.like("task_name", targetTable))
.orderByDesc("create_time")
);
return ApiResult.success(tablesViews);
} catch (Exception e) {
return ApiResult.error(401, e.getMessage());
}
}
/**
* 获取数据表属性
*
* @param taskId
* @return
*/
@GetMapping("/Sys/data/getTableDetail")
public ApiResult<TableInfo> getTableDetail(String taskId) {
// 获取基础数据
SyncTask task = syncTaskService.getById(taskId);
DbConfig dbConfig = configService.getById(task.getSourceDbId());
JdbcTemplate jdbcTemplate;
try {
// 统一创建JdbcTemplate避免重复初始化
jdbcTemplate = DataSourceConfig.createJdbcTemplate(dbConfig);
} catch (Exception e) {
return ApiResult.error(401, e.getMessage());
}
// 查询表基本信息
List<TabDetail> data;
try {
String tableQuerySql = "SELECT CREATE_TIME,TABLE_NAME,TABLE_COMMENT,MAX_DATA_LENGTH,UPDATE_TIME " +
"FROM information_schema.TABLES " +
"WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?";
data = jdbcTemplate.query(
querySql,
tableQuerySql,
(rs, rowNum) -> new TabDetail(
rs.getString("CREATE_TIME"),
dbConfig.getDbName(),
@@ -185,16 +275,17 @@ public class dataController {
);
data.sort(Comparator.comparing(TabDetail::getTableName));
} catch (Exception e) {
data = Collections.emptyList();
System.out.println(e.getMessage());
}
return ApiResult.error(401, e.getMessage());
}
// 查询表列信息
List<TabColumns> columns;
try {
JdbcTemplate jdbcTemplate = DataSourceConfig.createJdbcTemplate(dbConfig);
// 补充参数传递
String querySql = "SELECT TABLE_NAME,ORDINAL_POSITION,COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT,COLUMN_KEY FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?";
String columnQuerySql = "SELECT TABLE_NAME,ORDINAL_POSITION,COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT,COLUMN_KEY " +
"FROM information_schema.COLUMNS " +
"WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?";
columns = jdbcTemplate.query(
querySql,
columnQuerySql,
(rs, rowNum) -> new TabColumns(
rs.getString("TABLE_NAME"),
rs.getInt("ORDINAL_POSITION"),
@@ -208,26 +299,29 @@ public class dataController {
);
columns.sort(Comparator.comparing(TabColumns::getSort));
} catch (Exception e) {
columns = Collections.emptyList();
System.out.println(e.getMessage());
return ApiResult.error(401, e.getMessage());
}
// 在查询完表结构后
// 计算表结构统计信息
long primaryKeyCnt = columns.stream()
.filter(c -> "PRI".equalsIgnoreCase(c.getKeyType()))
.count();
long indexCnt = columns.stream()
.filter(c -> !"PRI".equalsIgnoreCase(c.getKeyType()) && !c.getKeyType().isBlank())
.count()
+ 1; // 主键索引也算 1
.count() + 1; // 包含主键索引
long colCnt = columns.size();
model.addAttribute("pkCnt", primaryKeyCnt);
model.addAttribute("idxCnt", indexCnt);
model.addAttribute("colCnt", colCnt);
model.addAttribute("data", data);
model.addAttribute("columns", columns);
model.addAttribute("ddlSql", buildDDL(columns, data.get(0)));
model.addAttribute("selectSql", buildSelect(columns, data.get(0)));
return "views/data/detail";
// 构建返回结果
TableInfo tableInfo = new TableInfo(
data.get(0),
columns,
primaryKeyCnt,
indexCnt,
colCnt,
buildDDL(columns, data.get(0)),
buildSelect(columns, data.get(0))
);
return ApiResult.success(tableInfo);
}

View File

@@ -0,0 +1,9 @@
package com.mini.capi.sys.App;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Sys/hosts")
public class hostController {
}

View File

@@ -1,4 +1,4 @@
package com.mini.capi.sys.pageController;
package com.mini.capi.sys.App;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mini.capi.biz.domain.ApiMenus;
@@ -10,6 +10,7 @@ import com.mini.capi.biz.service.ApiUserService;
import com.mini.capi.model.ApiResult;
import com.mini.capi.model.auth.Result;
import com.mini.capi.sys.domain.ModuleMenuDTO;
import com.mini.capi.utils.KeyUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import lombok.Data;
@@ -20,10 +21,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/Sys/login")
public class loginPageController {
public class loginController {
@Resource
@@ -58,11 +58,14 @@ public class loginPageController {
*/
private String uname;
private String token;
// 构造方法从实体类转换
public ApiUserDTO(ApiUser apiUser) {
public ApiUserDTO(ApiUser apiUser, String token) {
this.userId = apiUser.getUserId();
this.username = apiUser.getApiUser();
this.uname = apiUser.getUname();
this.token = token;
}
}
@@ -91,14 +94,25 @@ public class loginPageController {
// 可记录登录失败日志用于后续风控
return Result.error(102, "账户或密码错误");
}
session.setAttribute("token", apiUser);
ApiUserDTO userDTO = new ApiUserDTO(apiUser);
session.setAttribute("userInfo", apiUser);
ApiUserDTO userDTO = new ApiUserDTO(apiUser, KeyUtil.ObjKey(32, 0));
return Result.success("登录成功", userDTO);
} catch (Exception e) {
return Result.error(103, "登录失败,请稍后重试");
}
}
@PostMapping("/userLogout")
public Result loginOut(HttpSession session) {
try {
session.removeAttribute("userInfo"); // 只清 token
session.invalidate();
return Result.error(200, "退出成功");
} catch (Exception e) {
return Result.error(500, "退出失败");
}
}
@GetMapping("/getModules")
public ApiResult<List<ModuleMenuDTO>> getModules() {

View File

@@ -1,31 +1,40 @@
package com.mini.capi.sys.controller;
import jakarta.servlet.http.HttpServletRequest; // 注意这里
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.HashMap;
import java.util.Map;
@Controller
public class CustomErrorController implements ErrorController {
@RequestMapping("/error")
public ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request) {
public Object handleError(HttpServletRequest request) {
String uri = request.getRequestURI();
// 1. 前端路由:统一转发到 index.html
if (uri.startsWith("/cApi/index/")) {
return "forward:/index.html";
}
// 2. 其他 404返回 JSON
HttpStatus status = getStatus(request);
Map<String, Object> body = new HashMap<>();
body.put("status", status.value());
body.put("error", status.getReasonPhrase());
body.put("message", "访问的资源不存在");
body.put("path", request.getRequestURI());
return ResponseEntity.status(status).body(body);
return ResponseEntity
.status(status)
.body(Map.of(
"status", status.value(),
"error", status.getReasonPhrase(),
"message", "访问的资源不存在",
"path", uri
));
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer code = (Integer) request.getAttribute("jakarta.servlet.error.status_code");
return (code != null) ? HttpStatus.valueOf(code) : HttpStatus.INTERNAL_SERVER_ERROR;
return code != null ? HttpStatus.valueOf(code) : HttpStatus.INTERNAL_SERVER_ERROR;
}
}
}

View File

@@ -1,19 +0,0 @@
package com.mini.capi.sys.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class hostController {
/**
* 主机登录
*
* @return
*/
@GetMapping("/Sys/app/host")
public String listPage() {
return "views/ssh/index";
}
}

View File

@@ -1,40 +0,0 @@
package com.mini.capi.sys.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class loginController {
@GetMapping("/login")
public String loginPage() {
return "forward:/index.html";
}
//
// /**
// * 退出登录:清空 session 并返回到退出成功页面
// */
// @GetMapping("/userLogout")
// public String logout(HttpSession session) {
// session.invalidate();
// return "index";
// }
//
//
// /**
// * 主页
// */
// @GetMapping("/welcome")
// public String welcomePage() {
// return "views/demo";
// }
//
// /**
// * 系统首页-控制台
// */
// @GetMapping("/home")
// public String homePage() {
// return "views/home";
// }
}

View File

@@ -1,15 +0,0 @@
package com.mini.capi.sys.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class sysController {
@GetMapping("/Sys/sys/icon")
public String getIcon() {
return "views/icon";
}
}

View File

@@ -0,0 +1,28 @@
package com.mini.capi.sys.domain;
import lombok.Data;
import java.io.Serializable;
@Data
public class SelectOption implements Serializable {
private String value;
private String label;
private boolean disabled;
public SelectOption() {
}
// 全参构造函数
public SelectOption(String value, String label, boolean disabled) {
this.value = value;
this.label = label;
this.disabled = disabled;
}
}

View File

@@ -1,46 +0,0 @@
package com.mini.capi.sys.pageController;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mini.capi.biz.domain.DbConfig;
import com.mini.capi.biz.domain.SyncTablesView;
import com.mini.capi.biz.service.DbConfigService;
import com.mini.capi.biz.service.SyncTablesViewService;
import jakarta.annotation.Resource;
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.util.List;
@RestController // ← 关键
@RequestMapping("/Sys/data")
public class dataPageController {
@Resource
private DbConfigService configService;
@Resource
private SyncTablesViewService tablesViewService;
@GetMapping("/getDbList")
public List<DbConfig> getDbList() {
return configService.list();
}
@GetMapping("/getTableList")
public List<SyncTablesView> getTableList(String dbId, String targetTable) {
return tablesViewService.list(
new QueryWrapper<SyncTablesView>()
.eq(StringUtils.hasText(dbId), "db_id", dbId)
.and(StringUtils.hasText(targetTable),
w -> w.like("target_table", targetTable)
.or()
.like("task_name", targetTable))
.orderByDesc("create_time")
);
}
}

View File

@@ -1,45 +0,0 @@
package com.mini.capi.sys.pageController;
import com.mini.capi.model.ApiResult;
import com.mini.capi.model.TabResult;
import com.mini.capi.sys.service.DbService;
import com.mini.capi.utils.vToken;
import jakarta.annotation.Resource;
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("/Sys/dbs")
public class dbPageController {
@Resource
private DbService dbService;
/**
* 获取MySQL的当前连接下的所有数据表
*/
@GetMapping("/getApiSourceTables")
public ApiResult<List<TabResult>> listSourceTables(String token, String dbId) {
// 1. 验证token有效性
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dbService.listSourceTables(dbId);
}
/**
* 运行单个任务
*/
@GetMapping("/getTaskSyncDbByInfo")
public ApiResult<?> jobSyncOneTask(String token, String taskId) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return dbService.jobSyncOneTask(taskId);
}
}

View File

@@ -1,70 +0,0 @@
package com.mini.capi.sys.pageController;
import com.mini.capi.model.ApiResult;
import com.mini.capi.sys.service.HostService;
import com.mini.capi.utils.vToken;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RestController
@RequestMapping("/Sys/hosts")
public class hostPageController {
@Resource
private HostService hostService;
@GetMapping("/getApiInfo")
public ApiResult<List<HostService.SnapshotDTO>> getApiInfo(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.getApiInfo();
}
/**
* 获取容器列表
*/
@GetMapping("/getApiDockerInfo")
public ApiResult<?> getDockerInfo(String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.getDockerInfo();
}
/**
* 启动容器
*/
@GetMapping("/getApiStartDockerInfo")
public ApiResult<?> startDockerInfo(String id, String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.startDockerInfo(id);
}
/**
* 停止容器
*/
@GetMapping("/getApiStopDockerInfo")
public ApiResult<?> stopDockerInfo(String id, String token) {
if (vToken.isValidToken(token)) {
return ApiResult.error(401, "无效的访问令牌");
}
return hostService.stopDockerInfo(id);
}
}

View File

@@ -0,0 +1,81 @@
package com.mini.capi.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.net.util.Base64;
public class AESUtil {
public static String key = "AD42F6697B035B7580E4FEF93BE20BAD";
private static String charset = "utf-8";
// 偏移量
private static int offset = 16;
private static String transformation = "AES/CBC/PKCS5Padding";
private static String algorithm = "AES";
/**
* 加密
*
* @param content
* @return
*/
public static String encrypt(String content) {
return encrypt(content, key);
}
/**
* 解密
*
* @param content
* @return
*/
public static String decrypt(String content) {
return decrypt(content, key);
}
/**
* 加密
*
* @param content 需要加密的内容
* @param key 加密密码
* @return
*/
public static String encrypt(String content, String key) {
try {
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), algorithm);
IvParameterSpec iv = new IvParameterSpec(key.getBytes(), 0, offset);
Cipher cipher = Cipher.getInstance(transformation);
byte[] byteContent = content.getBytes(charset);
cipher.init(Cipher.ENCRYPT_MODE, skey, iv);// 初始化
byte[] result = cipher.doFinal(byteContent);
return new Base64().encodeToString(result).replaceAll("[\\s*\t\n\r]", ""); // 加密
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
/**
* AES256解密
*
* @param content 待解密内容
* @param key 解密密钥
* @return 解密之后
* @throws Exception
*/
public static String decrypt(String content, String key) {
try {
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), algorithm);
IvParameterSpec iv = new IvParameterSpec(key.getBytes(charset), 0, offset);
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.DECRYPT_MODE, skey, iv);// 初始化
byte[] result = cipher.doFinal(new Base64().decode(content));
return new String(result).replaceAll("[\\s*\t\n\r]", ""); // 解密
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
}

View File

@@ -0,0 +1,48 @@
package com.mini.capi.utils;
import java.util.Random;
public class KeyUtil {
public static String ObjKey(int length, int type) {
Random random = new Random();
StringBuffer key = new StringBuffer();
if (type == 1) {
String str = "0123456789";
for (int i = 0; i < length; ++i) {
//从62个的数字或字母中选择
int number = random.nextInt(10);
//将产生的数字通过length次承载到key中
key.append(str.charAt(number));
}
return key.toString();
} else if (type == 2) {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for (int i = 0; i < length; ++i) {
//从62个的数字或字母中选择
int number = random.nextInt(36);
//将产生的数字通过length次承载到key中
key.append(str.charAt(number));
}
return key.toString();
} else if (type == 3) {
String str = "abcdefghijklmnopqrstuvwxyz0123456789";
for (int i = 0; i < length; ++i) {
//从62个的数字或字母中选择
int number = random.nextInt(36);
//将产生的数字通过length次承载到key中
key.append(str.charAt(number));
}
return key.toString();
} else {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (int i = 0; i < length; ++i) {
//从62个的数字或字母中选择
int number = random.nextInt(62);
//将产生的数字通过length次承载到key中
key.append(str.charAt(number));
}
return key.toString();
}
}
}

View File

@@ -30,4 +30,5 @@ webssh.file.upload-max-size=100MB
webssh.file.temp-dir=/ogsapp/temp/webssh-uploads
webssh.collaboration.enabled=true
webssh.collaboration.max-participants=10
webssh.collaboration.session-timeout=3600000
webssh.collaboration.session-timeout=3600000
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

View File

@@ -1 +0,0 @@
const n={};n.render=function(n,e){return null};export{n as default};

View File

@@ -1 +0,0 @@
@charset "UTF-8";.login-wrapper[data-v-c93922d0]{height:100vh;display:flex;align-items:center;justify-content:flex-end;padding-right:200px;background:linear-gradient(120deg,rgba(79,172,254,.7) 0%,rgba(0,242,254,.7) 50%,rgba(122,90,248,.7) 100%),url(/cApi/assets/backImg.5cfc718b.jpg) center center no-repeat;background-blend-mode:overlay;background-size:cover}.login-text[data-v-c93922d0]{text-align:center;color:#fff;width:800px;padding:32px 48px;border-radius:8px}.login-card[data-v-c93922d0]{width:520px;padding:32px 48px;border-radius:8px;box-shadow:0 8px 24px #0000001f}.login-header[data-v-c93922d0]{text-align:center;margin-bottom:32px}.login-header .logo[data-v-c93922d0]{width:64px;height:64px;margin-bottom:12px}.login-header h1[data-v-c93922d0]{font-size:24px;font-weight:600;margin:0}.login-header p[data-v-c93922d0]{font-size:14px;color:#8c8c8c;margin:8px 0 0}

View File

@@ -0,0 +1 @@
@charset "UTF-8";.login-wrapper[data-v-c077d3e4]{height:100vh;display:flex;align-items:center;justify-content:flex-end;padding-right:200px;background:linear-gradient(120deg,rgba(79,172,254,.7) 0%,rgba(0,242,254,.7) 50%,rgba(122,90,248,.7) 100%),url(/cApi/assets/backImg.5cfc718b.jpg) center center no-repeat;background-blend-mode:overlay;background-size:cover}.login-text[data-v-c077d3e4]{text-align:center;color:#fff;width:800px;padding:32px 48px;border-radius:8px}.login-card[data-v-c077d3e4]{width:520px;padding:32px 48px;border-radius:8px;box-shadow:0 8px 24px #0000001f}.login-header[data-v-c077d3e4]{text-align:center;margin-bottom:32px}.login-header .logo[data-v-c077d3e4]{width:64px;height:64px;margin-bottom:12px}.login-header h1[data-v-c077d3e4]{font-size:24px;font-weight:600;margin:0}.login-header p[data-v-c077d3e4]{font-size:14px;color:#8c8c8c;margin:8px 0 0}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{d as S,_ as E,a as h,u as D,r as f,b as k,o as w,c as y,e as u,w as o,f as s,g as c,h as _,U as x,L as b,i as L,m}from"./index.04365c99.js";import{a as N}from"./auth.545ce83f.js";var O="/cApi/assets/logo.03d6d6da.png";const U=S("auth",{state:()=>({token:localStorage.getItem("token")||null,userInfo:localStorage.getItem("userInfo")?JSON.parse(localStorage.getItem("userInfo")):null}),actions:{setAuthInfo(i,r){this.token=i,this.userInfo=r,localStorage.setItem("token",i),localStorage.setItem("userInfo",JSON.stringify(r))},clearAuthInfo(){this.token=null,this.userInfo=null,localStorage.removeItem("token"),localStorage.removeItem("userInfo")}}});const J={class:"login-wrapper"},R=h({__name:"Login",setup(i){const r=D(),g=f(),n=f(!1),t=k({account:"",password:""}),F={account:[{required:!0,message:"\u8BF7\u8F93\u5165\u7528\u6237\u540D"}],password:[{required:!0,message:"\u8BF7\u8F93\u5165\u5BC6\u7801"}]},B=async()=>{if(n.value)return;n.value=!0;const p=U();try{const e=await N(t);if(e.code===200&&e.data){const l=e.data.token,a=JSON.stringify(e.data);localStorage.setItem("token",l),localStorage.setItem("userInfo",a),p.setAuthInfo(l,a),m.success(e.msg||"\u767B\u5F55\u6210\u529F"),setTimeout(()=>{r.replace("/index/console")},800);return}m.error(e.msg||"\u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u8D26\u53F7\u5BC6\u7801")}catch(e){console.error("\u767B\u5F55\u8BF7\u6C42\u5F02\u5E38:",e),m.error("\u7F51\u7EDC\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u540E\u91CD\u8BD5")}finally{n.value=!1}};return(p,e)=>{const l=s("a-input"),a=s("a-form-item"),v=s("a-input-password"),I=s("a-button"),A=s("a-form"),C=s("a-card");return w(),y("div",J,[u(C,{class:"login-card",bordered:!1},{default:o(()=>[e[3]||(e[3]=c("div",{class:"login-header"},[c("img",{class:"logo",src:O,alt:"logo"}),c("h1",null,"cApi\u7BA1\u7406\u7CFB\u7EDF"),c("p",null,"\u5B89\u5168\u3001\u9AD8\u6548\u7684\u4E00\u7AD9\u5F0F\u7BA1\u7406\u89E3\u51B3\u65B9\u6848\uFF0C\u4E3A\u60A8\u7684\u4E1A\u52A1\u4FDD\u9A7E\u62A4\u822A")],-1)),u(A,{ref_key:"formRef",ref:g,model:t,rules:F,size:"large",onFinish:B},{default:o(()=>[u(a,{name:"account"},{default:o(()=>[u(l,{value:t.account,"onUpdate:value":e[0]||(e[0]=d=>t.account=d),placeholder:"\u8BF7\u8F93\u5165\u7528\u6237\u540D","allow-clear":""},{prefix:o(()=>[u(_(x))]),_:1},8,["value"])]),_:1}),u(a,{name:"password"},{default:o(()=>[u(v,{value:t.password,"onUpdate:value":e[1]||(e[1]=d=>t.password=d),placeholder:"\u8BF7\u8F93\u5165\u5BC6\u7801","allow-clear":""},{prefix:o(()=>[u(_(b))]),_:1},8,["value"])]),_:1}),u(a,null,{default:o(()=>[u(I,{type:"primary","html-type":"submit",loading:n.value,block:""},{default:o(()=>[...e[2]||(e[2]=[L(" \u767B\u5F55 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])]),_:1})])}}});var T=E(R,[["__scopeId","data-v-c077d3e4"]]);export{T as default};

View File

@@ -0,0 +1 @@
import{_ as r}from"./index.04365c99.js";const e={};function j(_,c){return" jjjjjjjjj "}var t=r(e,[["render",j]]);export{t as default};

View File

@@ -0,0 +1 @@
import{_ as r}from"./index.04365c99.js";const e={};function t(_,c){return" \u9876\u9876\u9876\u9876\u9876\u9876\u9876\u9876\u9876\u9876\u9876\u9876\u9876\u9876 "}var o=r(e,[["render",t]]);export{o as default};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.icon-gallery[data-v-64d10c62]{width:100%;box-sizing:border-box}.search-input[data-v-64d10c62]{max-width:400px}.icons-grid[data-v-64d10c62]{width:100%;box-sizing:border-box}.icon-item[data-v-64d10c62]:hover{border-color:#1890ff;box-shadow:0 2px 8px #00000014}.icon-name[data-v-64d10c62]{font-size:12px;color:#595959;text-align:center;word-break:break-all;max-width:100%}.copy-buttons[data-v-64d10c62]{display:flex;gap:8px;margin-top:8px;width:100%;justify-content:center}.copy-btn[data-v-64d10c62]{padding:2px 8px!important;font-size:12px!important}.empty-state[data-v-64d10c62]{padding:40px 0;text-align:center}.copy-message[data-v-64d10c62]{position:fixed;bottom:24px;left:50%;transform:translate(-50%);z-index:1000}

View File

@@ -0,0 +1 @@
import{_ as U,a as W,I as q,r as a,n as u,o as s,c as l,j as g,t as p,g as w,F as G,y as H,A as m,e as r,f as y,z as J,v as K,w as S,h as F,D as T,i as z,k as B}from"./index.04365c99.js";const Q=["onMouseenter"],X={class:"icon-name"},Y={key:0,class:"copy-buttons"},Z={key:1,class:"empty-state"},ee=W({__name:"icon",props:{showSearch:{type:Boolean,default:!0},searchSize:{type:String,default:"middle"},columns:{type:Number,default:6},iconSize:{type:Number,default:24},itemPadding:{type:String,default:"16px"},messageDuration:{type:Number,default:2e3}},setup(c){const n=c,N=["createFromIconfontCN","getTwoToneColor","setTwoToneColor","default","CopyOutlined"],_=Object.entries(q).filter(([e])=>!N.includes(e)).map(([e,t])=>({name:e,component:t})),i=a(""),C=u(()=>i.value?_.filter(({name:e})=>e.toLowerCase().includes(i.value.toLowerCase())):_),f=a(""),v=a(!1),h=a(""),D=a("success");function M(e){f.value=e}function $(){f.value=""}function E(e){const t=`<${e} />`;x(t).then(()=>{d(`\u5DF2\u590D\u5236: ${t}`,"success")}).catch(()=>{d("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u590D\u5236","error")})}function I(e){x(e).then(()=>{d(`\u5DF2\u590D\u5236: ${e}`,"success")}).catch(()=>{d("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u590D\u5236","error")})}async function x(e){try{return await navigator.clipboard.writeText(e),!0}catch(t){return console.error("\u65E0\u6CD5\u590D\u5236\u6587\u672C: ",t),!1}}function d(e,t){h.value=e,D.value=t,v.value=!0,setTimeout(()=>{v.value=!1},n.messageDuration)}const L=u(()=>({padding:"16px",backgroundColor:"#f5f5f5",borderRadius:"4px"})),A=u(()=>({display:"grid",gridTemplateColumns:`repeat(${n.columns}, 1fr)`,gap:"12px",marginTop:n.showSearch?"16px":0})),V=u(()=>({display:"flex",flexDirection:"column",alignItems:"center",backgroundColor:"#fff",border:"1px solid #e8e8e8",borderRadius:"6px",padding:n.itemPadding,cursor:"pointer",transition:"all 0.2s"})),O=u(()=>({fontSize:`${n.iconSize}px`,color:"#262626",marginBottom:"8px"}));return(e,t)=>{const j=y("a-input"),b=y("a-button"),P=y("a-empty"),R=y("a-message");return s(),l("div",{class:"icon-gallery",style:m(L.value)},[c.showSearch?(s(),g(j,{key:0,value:i.value,"onUpdate:value":t[0]||(t[0]=o=>i.value=o),placeholder:"\u641C\u7D22\u56FE\u6807\u540D\u79F0...","allow-clear":"",class:"search-input",size:c.searchSize},null,8,["value","size"])):p("",!0),w("div",{class:"icons-grid",style:m(A.value)},[(s(!0),l(G,null,H(C.value,o=>(s(),l("div",{key:o.name,class:"icon-item",style:m(V.value),onMouseenter:k=>M(o.name),onMouseleave:$},[(s(),g(J(o.component),{class:"icon",style:m(O.value)},null,8,["style"])),w("span",X,K(o.name),1),f.value===o.name?(s(),l("div",Y,[r(b,{type:"primary",size:"small",onClick:B(k=>E(o.name),["stop"]),class:"copy-btn"},{default:S(()=>[r(F(T),{class:"mr-1"}),t[1]||(t[1]=z("\u6807\u7B7E ",-1))]),_:1},8,["onClick"]),r(b,{type:"default",size:"small",onClick:B(k=>I(o.name),["stop"]),class:"copy-btn"},{default:S(()=>[r(F(T),{class:"mr-1"}),t[2]||(t[2]=z("\u540D\u79F0 ",-1))]),_:1},8,["onClick"])])):p("",!0)],44,Q))),128))],4),C.value.length===0?(s(),l("div",Z,[r(P,{description:"\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u56FE\u6807"})])):p("",!0),v.value?(s(),g(R,{key:2,content:h.value,type:D.value,duration:c.messageDuration,class:"copy-message"},null,8,["content","type","duration"])):p("",!0)],4)}}});var oe=U(ee,[["__scopeId","data-v-64d10c62"]]);export{oe as default};

View File

@@ -0,0 +1 @@
import{_ as r}from"./index.04365c99.js";const e={};function _(c,n){return" app "}var a=r(e,[["render",_]]);export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}@-ms-viewport{width:device-width}body{margin:0}[tabindex="-1"]:focus{outline:none}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;font-weight:500}p{margin-top:0;margin-bottom:1em}abbr[title],abbr[data-original-title]{-webkit-text-decoration:underline dotted;text-decoration:underline;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}pre,code,kbd,samp{font-size:1em;font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace}pre{margin-top:0;margin-bottom:1em;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}a,area,button,[role=button],input:not([type="range"]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;text-align:left;caption-side:bottom}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#feffe6}

View File

@@ -0,0 +1 @@
.empty-page-container[data-v-2de931e9]{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:#fff;border-radius:8px;box-shadow:0 1px 2px #0000000d}.empty-content[data-v-2de931e9]{width:100%;max-width:600px;padding:48px 24px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:20px}.empty-icon[data-v-2de931e9]{width:80px;height:80px;border-radius:50%;background-color:#e8f4ff;display:flex;align-items:center;justify-content:center;color:#1890ff}.empty-icon[data-v-2de931e9] svg{width:40px;height:40px}.empty-title[data-v-2de931e9]{font-size:18px;font-weight:500;color:#333;margin:0}.empty-desc[data-v-2de931e9]{font-size:14px;color:#666;line-height:1.6;margin:0}.empty-actions[data-v-2de931e9]{display:flex;gap:12px;margin-top:8px}.empty-meta[data-v-2de931e9]{margin-top:16px;display:flex;flex-wrap:wrap;justify-content:center;gap:16px;font-size:12px;color:#999}@media (max-width: 768px){.empty-content[data-v-2de931e9]{padding:32px 16px;gap:16px}.empty-icon[data-v-2de931e9]{width:64px;height:64px}.empty-icon[data-v-2de931e9] svg{width:32px;height:32px}.empty-title[data-v-2de931e9]{font-size:16px}.empty-meta[data-v-2de931e9]{flex-direction:column;gap:8px}}

View File

@@ -1 +0,0 @@
import{r as e,o as r,c as t,a as o,b as n,d as s,A as i}from"./vendor.a8167e4a.js";!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver((e=>{for(const t of e)if("childList"===t.type)for(const e of t.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)})).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerpolicy&&(r.referrerPolicy=e.referrerpolicy),"use-credentials"===e.crossorigin?r.credentials="include":"anonymous"===e.crossorigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();const c={};c.render=function(o,n){const s=e("router-view");return r(),t(s)};const a={},d=function(e,r){return r&&0!==r.length?Promise.all(r.map((e=>{if((e=`/cApi/${e}`)in a)return;a[e]=!0;const r=e.endsWith(".css"),t=r?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${t}`))return;const o=document.createElement("link");return o.rel=r?"stylesheet":"modulepreload",r||(o.as="script",o.crossOrigin=""),o.href=e,document.head.appendChild(o),r?new Promise(((e,r)=>{o.addEventListener("load",e),o.addEventListener("error",r)})):void 0}))).then((()=>e())):e()},l=[{path:"/",redirect:"/login"},{path:"/login",name:"Login",component:()=>d((()=>import("./Login.ab12ce3d.js")),["assets/Login.ab12ce3d.js","assets/Login.008b81ee.css","assets/vendor.a8167e4a.js"])},{path:"/dashboard",name:"Dashboard",component:()=>d((()=>import("./Dashboard.cd76d04c.js")),[]),meta:{requiresAuth:!0}}],u=o({history:n("/cApi/"),routes:l});s(c).use(i).use(u).mount("#app");

View File

@@ -0,0 +1,4 @@
import{_ as B,a as E,r as d,o as p,c as r,g as e,e as t,h as a,E as A,i as s,w as F,f as m,P as c,Q as C}from"./index.04365c99.js";const _={class:"empty-page-container"},D={class:"empty-content"},v={class:"empty-icon"},y={class:"empty-actions"},f=E({__name:"index",setup(x){const n=d("\u7A7A\u767D\u6A21\u677F\u9875\u9762"),l=()=>{console.log(`[${n.value}] \u89E6\u53D1\u300C\u521B\u5EFA\u5185\u5BB9\u300D\u64CD\u4F5C`),alert("\u53EF\u5728\u6B64\u5904\u5B9E\u73B0\u300C\u521B\u5EFA\u5185\u5BB9\u300D\u7684\u4E1A\u52A1\u903B\u8F91")},i=()=>{console.log(`[${n.value}] \u67E5\u770B\u4F7F\u7528\u6307\u5357`),alert(`\u4F7F\u7528\u6307\u5357\uFF1A
1. \u6B64\u9875\u9762\u5DF2\u9002\u914D\u7236\u5BB9\u5668\u81EA\u9002\u5E94\u5C3A\u5BF8
2. \u53EF\u5728 empty-content \u5185\u6DFB\u52A0\u4E1A\u52A1\u7EC4\u4EF6
3. \u6837\u5F0F\u53EF\u53C2\u8003\u539F\u9879\u76EE\u89C4\u8303\u8C03\u6574`)};return(g,u)=>{const o=m("a-button");return p(),r("div",_,[e("div",D,[e("div",v,[t(a(A))]),u[2]||(u[2]=e("h2",{class:"empty-title"},"\u8FD9\u662F\u4E00\u4E2A\u7A7A\u767D\u9875\u9762",-1)),u[3]||(u[3]=e("p",{class:"empty-desc"},[s(" \u4F60\u53EF\u4EE5\u5728\u8FD9\u91CC\u6269\u5C55\u529F\u80FD\uFF0C\u6BD4\u5982\u6DFB\u52A0\u6570\u636E\u5C55\u793A\u3001\u8868\u5355\u63D0\u4EA4\u3001\u56FE\u8868\u5206\u6790\u7B49\u5185\u5BB9"),e("br"),s(" \u9875\u9762\u5DF2\u9002\u914D\u7236\u5BB9\u5668\u5C3A\u5BF8\uFF0C\u652F\u6301\u9AD8\u5EA6/\u5BBD\u5EA6\u81EA\u9002\u5E94 ")],-1)),e("div",y,[t(o,{type:"primary",onClick:l},{default:F(()=>[t(a(c),{class:"mr-2"}),u[0]||(u[0]=s(" \u521B\u5EFA\u5185\u5BB9 ",-1))]),_:1}),t(o,{onClick:i,style:{"margin-left":"12px"}},{default:F(()=>[t(a(C),{class:"mr-2"}),u[1]||(u[1]=s(" \u67E5\u770B\u4F7F\u7528\u6307\u5357 ",-1))]),_:1})]),u[4]||(u[4]=e("div",{class:"empty-meta"},[e("span",{class:"meta-item"},"\u9875\u9762\u8DEF\u5F84\uFF1A@/views/EmptyTemplatePage.vue"),e("span",{class:"meta-item"},"\u9002\u914D\u573A\u666F\uFF1A\u5217\u8868\u9875\u3001\u8BE6\u60C5\u9875\u3001\u8868\u5355\u9875\u7B49\u521D\u59CB\u6A21\u677F")],-1))])])}}});var N=B(f,[["__scopeId","data-v-2de931e9"]]);export{N as default};

View File

@@ -0,0 +1 @@
html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}@-ms-viewport{width:device-width}body{margin:0}[tabindex="-1"]:focus{outline:none}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;font-weight:500}p{margin-top:0;margin-bottom:1em}abbr[title],abbr[data-original-title]{-webkit-text-decoration:underline dotted;text-decoration:underline;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}pre,code,kbd,samp{font-size:1em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}pre{margin-top:0;margin-bottom:1em;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}a,area,button,[role=button],input:not([type="range"]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;text-align:left;caption-side:bottom}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#feffe6}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -4,10 +4,9 @@
<meta charset="UTF-8" />
<link rel="icon" href="/cApi/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script type="module" crossorigin src="/cApi/assets/index.8dd9ceba.js"></script>
<link rel="modulepreload" href="/cApi/assets/vendor.a8167e4a.js">
<link rel="stylesheet" href="/cApi/assets/index.6a28b391.css">
<title>cApi系统管理</title>
<script type="module" crossorigin src="/cApi/assets/index.04365c99.js"></script>
<link rel="stylesheet" href="/cApi/assets/index.fc5e98cf.css">
</head>
<body>
<div id="app"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB