diff --git a/web-api/src/main/java/com/jeesite/modules/app/Job/dataJob.java b/web-api/src/main/java/com/jeesite/modules/app/Job/dataJob.java index d2ced8b8..a2be05f4 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/Job/dataJob.java +++ b/web-api/src/main/java/com/jeesite/modules/app/Job/dataJob.java @@ -1,12 +1,17 @@ package com.jeesite.modules.app.Job; + import com.jeesite.modules.app.dao.TableTree; import com.jeesite.modules.app.utils.LoggerUtils; +import com.jeesite.modules.app.utils.MyFileUtils; import com.jeesite.modules.app.utils.MysqlUtils; +import com.jeesite.modules.app.utils.vDate; import com.jeesite.modules.biz.entity.BizDbConfig; +import com.jeesite.modules.biz.entity.BizExecScript; import com.jeesite.modules.biz.entity.BizTableField; import com.jeesite.modules.biz.entity.BizTableInfo; import com.jeesite.modules.biz.service.BizDbConfigService; +import com.jeesite.modules.biz.service.BizExecScriptService; import com.jeesite.modules.biz.service.BizTableFieldService; import com.jeesite.modules.biz.service.BizTableInfoService; import jakarta.annotation.Resource; @@ -14,8 +19,10 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Controller; +import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -30,6 +37,9 @@ public class dataJob { @Resource private BizTableFieldService tableFieldService; + @Resource + private BizExecScriptService bizExecScriptService; + @Resource(name = "hostMonitorExecutor") private ThreadPoolTaskExecutor hostMonitorExecutor; @@ -71,4 +81,33 @@ public class dataJob { logger.error(e.getMessage()); } } + + + @Scheduled(cron = "0 30 0 * * ?") + public void getExecScript() { + BizExecScript execScript = new BizExecScript(); + execScript.setDataStatus("1"); + List bizExecScriptList = bizExecScriptService.findList(execScript); + List> futures = new ArrayList<>(bizExecScriptList.size()); + for (BizExecScript script : bizExecScriptList) { + CompletableFuture future = CompletableFuture.runAsync(() -> { + try { + BizDbConfig dbConfig = dbConfigService.get(script.getDbId()); + String result = MysqlUtils.getExecScript(dbConfig, script.getScriptName()); + script.setExecResult(result); + script.setUpdateTime(vDate.getNow()); + bizExecScriptService.save(script); + } catch (Exception e) { + logger.error(e.getMessage()); + } + }, hostMonitorExecutor); // 指定使用配置的线程池 + futures.add(future); + } + try { + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .get(30, TimeUnit.SECONDS); + } catch (Exception e) { + logger.error(e.getMessage()); + } + } } diff --git a/web-api/src/main/java/com/jeesite/modules/app/dao/ExecResult.java b/web-api/src/main/java/com/jeesite/modules/app/dao/ExecResult.java index 627d0fde..41c288b1 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/dao/ExecResult.java +++ b/web-api/src/main/java/com/jeesite/modules/app/dao/ExecResult.java @@ -11,11 +11,14 @@ public class ExecResult implements Serializable { private String fileName; + private String error; + public ExecResult() { } - public ExecResult(String code, String fileName) { + public ExecResult(String code, String fileName, String error) { this.code = code; this.fileName = fileName; + this.error = error; } } diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java b/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java index 7c3ac9da..e4eca93d 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java @@ -1,8 +1,13 @@ package com.jeesite.modules.app.utils; import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; public class MyFileUtils { @@ -93,6 +98,65 @@ public class MyFileUtils { } + public static List getFilesDir(String dirPath) { + if (dirPath == null || dirPath.trim().isEmpty()) { + throw new IllegalArgumentException("目录路径不能为空!"); + } + File directory = new File(dirPath); + + if (!directory.exists()) { + throw new IllegalArgumentException("指定路径不存在:" + dirPath); + } + if (!directory.isDirectory()) { + throw new IllegalArgumentException("指定路径不是目录:" + dirPath); + } + File[] allFiles = directory.listFiles(); + List fileList = new ArrayList<>(); + if (allFiles != null) { + for (File file : allFiles) { + if (file.isFile()) { + fileList.add(file); + } + } + } + return fileList; + } + + /** + * 文件写入 + */ + public static void writeFile(String fileName, String content, boolean is_append) { + try { + writeToFile(fileName, content, StandardCharsets.UTF_8, is_append); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + + public static void writeToFile(String fileName, String content, java.nio.charset.Charset charset, boolean append) throws Exception { + if (fileName == null || fileName.trim().isEmpty()) { + throw new IllegalArgumentException("文件名不能为空"); + } + if (content == null) { + content = ""; + } + File file = new File(fileName); + File parentDir = file.getParentFile(); + if (parentDir != null && !parentDir.exists()) { + boolean dirCreated = parentDir.mkdirs(); + if (!dirCreated) { + throw new Exception("创建父目录失败: " + parentDir.getAbsolutePath()); + } + } + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file, append), charset)) { + writer.write(content + "\n"); + writer.flush(); + } catch (Exception e) { + throw new Exception("写入文件失败: " + file.getAbsolutePath(), e); + } + } + + public static String getIcon(String ext) { switch (ext) { case "wps": diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/MysqlUtils.java b/web-api/src/main/java/com/jeesite/modules/app/utils/MysqlUtils.java index 8ef5c479..41cb7d72 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/utils/MysqlUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/app/utils/MysqlUtils.java @@ -10,6 +10,9 @@ import com.jeesite.modules.biz.entity.BizDbConfig; import com.jeesite.modules.biz.entity.BizTableField; import com.jeesite.modules.biz.entity.BizTableInfo; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.*; @@ -24,8 +27,10 @@ public class MysqlUtils { private static final String filePath = "/ogsapp/resultList/"; + private static final String EXEC_RUN_PATH = "/ogsapp/script/sql/"; + private static final String EXEC_LOG_PATH = "/ogsapp/script/log/"; + private static String EXEC_CODE = "0"; - private static String EXEC_FILE = ""; // 需要排除的系统数据库 private static final List SYSTEM_DATABASES = Arrays.asList( @@ -214,8 +219,9 @@ public class MysqlUtils { public static ExecResult getExecResult(BizDbConfig dbConfig, String sql) { + String EXEC_RESULT = "执行成功"; + String EXEC_FILE = null; try { - EXEC_FILE = null; Connection conn = getConnection(dbConfig.getDbIp(), dbConfig.getDbPort(), dbConfig.getDbUsername(), dbConfig.getDbPassword()); Statement statement = conn.createStatement(); boolean isQuery = sql.trim().toUpperCase().startsWith("SELECT"); @@ -247,8 +253,102 @@ public class MysqlUtils { } } catch (Exception e) { EXEC_CODE = "0"; + EXEC_RESULT = e.getMessage(); logger.error(e.getMessage()); } - return new ExecResult(EXEC_CODE, EXEC_FILE); + return new ExecResult(EXEC_CODE, EXEC_FILE, EXEC_RESULT); + } + + + /** + * 脚本执行 + * + * @return + */ + public static String getExecScript(BizDbConfig dbConfig, String scriptName) { + String EXEC_RESULT = "执行成功"; + String LOG_NAME = EXEC_LOG_PATH + vId.getCid() + "_log_" + scriptName; + MyFileUtils.writeFile(LOG_NAME, "-- 执行脚本:" + scriptName + ",开始时间:" + vDate.getNow(), true); + Connection conn = null; + try { + File file = new File(EXEC_RUN_PATH + scriptName); + conn = getConnection(dbConfig.getDbIp(), dbConfig.getDbPort(), + dbConfig.getDbUsername(), dbConfig.getDbPassword()); + conn.setAutoCommit(false); + try (Statement statement = conn.createStatement(); + BufferedReader reader = new BufferedReader(new FileReader(file))) { + StringBuilder sqlContent = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.isEmpty() || line.startsWith("--")) { + continue; + } + sqlContent.append(line); + } + Map varMap = new HashMap<>(); + varMap.put("\\$\\{[bB][iI][zZ]_[dD][aA][tT][eE]\\}", vDate.dsValueDaysAgo(1)); + String replacedSqlContent = sqlContent.toString(); + for (Map.Entry entry : varMap.entrySet()) { + replacedSqlContent = replacedSqlContent.replaceAll(entry.getKey(), entry.getValue()); + } + String[] sqlStatements = replacedSqlContent.split(";"); + int totalAffectedRows = 0; + for (String sql : sqlStatements) { + sql = sql.trim(); + if (sql.isEmpty()) { + continue; + } + MyFileUtils.writeFile(LOG_NAME, sql, true); + boolean hasResultSet = statement.execute(sql); + if (hasResultSet) { + try (ResultSet rs = statement.getResultSet()) { + ResultSetMetaData metaData = rs.getMetaData(); + int columnCount = metaData.getColumnCount(); + StringBuilder header = new StringBuilder(); + for (int i = 1; i <= columnCount; i++) { + header.append(metaData.getColumnName(i)).append("\t"); + } + MyFileUtils.writeFile(LOG_NAME, header.toString().trim(), true); + int rowNum = 0; + while (rs.next()) { + rowNum++; + StringBuilder rowData = new StringBuilder(); + for (int i = 1; i <= columnCount; i++) { + Object value = rs.getObject(i); + rowData.append(value == null ? "NULL" : value.toString()).append("\t"); + } + MyFileUtils.writeFile(LOG_NAME, rowData.toString().trim(), true); + } + logger.info(sql, "执行成功,总行数:", rowNum); + } + } else { + int affectedRows = statement.getUpdateCount(); + totalAffectedRows += affectedRows; + logger.info(sql, "执行成功, 影响行数:", affectedRows); + } + } + conn.commit(); + MyFileUtils.writeFile(LOG_NAME, "-- 执行脚本:" + scriptName + ",结束时间:" + vDate.getNow(), true); + logger.info(file.getName(), "脚本影响行数:", totalAffectedRows, " 执行结果:", EXEC_RESULT); + } catch (Exception e) { + conn.rollback(); + EXEC_RESULT = e.getMessage(); + logger.error(file.getName(), "执行脚本文件失败:", e); + } + } catch (Exception e) { + EXEC_RESULT = e.getMessage(); + logger.error("执行脚本入口异常", e); + } finally { + // 最终关闭连接 + if (conn != null) { + try { + conn.close(); + } catch (Exception e) { + logger.error("关闭数据库连接失败", e); + } + } + } + return EXEC_RESULT; } } \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/dao/BizExecScriptDao.java b/web-api/src/main/java/com/jeesite/modules/biz/dao/BizExecScriptDao.java new file mode 100644 index 00000000..65600c18 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/dao/BizExecScriptDao.java @@ -0,0 +1,15 @@ +package com.jeesite.modules.biz.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.biz.entity.BizExecScript; + +/** + * 脚本信息DAO接口 + * @author gaoxq + * @version 2026-01-02 + */ +@MyBatisDao(dataSourceName="work") +public interface BizExecScriptDao extends CrudDao { + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/entity/BizExecScript.java b/web-api/src/main/java/com/jeesite/modules/biz/entity/BizExecScript.java new file mode 100644 index 00000000..f30155e9 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/entity/BizExecScript.java @@ -0,0 +1,101 @@ +package com.jeesite.modules.biz.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.jeesite.common.mybatis.annotation.JoinTable; +import com.jeesite.common.mybatis.annotation.JoinTable.Type; +import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.validation.constraints.Size; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.common.utils.excel.annotation.ExcelField; +import com.jeesite.common.utils.excel.annotation.ExcelField.Align; +import com.jeesite.common.utils.excel.annotation.ExcelFields; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; + +/** + * 脚本信息Entity + * + * @author gaoxq + * @version 2026-01-02 + */ +@EqualsAndHashCode(callSuper = true) +@Table(name = "biz_exec_script", alias = "a", label = "脚本信息信息", columns = { + @Column(name = "create_time", attrName = "createTime", label = "记录时间", isUpdate = false, isUpdateForce = true), + @Column(name = "id", attrName = "id", label = "唯一标识", isPK = true), + @Column(name = "script_desc", attrName = "scriptDesc", label = "脚本描述", queryType = QueryType.LIKE), + @Column(name = "script_name", attrName = "scriptName", label = "脚本名称", isQuery = false), + @Column(name = "script_text", attrName = "scriptText", label = "脚本内容", isQuery = false), + @Column(name = "db_id", attrName = "dbId", label = "执行标识", isQuery = false), + @Column(name = "data_status", attrName = "dataStatus", label = "数据状态"), + @Column(name = "exec_result", attrName = "execResult", label = "执行结果"), + @Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true), +}, joinTable = { + @JoinTable(type = Type.LEFT_JOIN, entity = BizDbConfig.class, attrName = "this", alias = "b", + on = "a.db_id = b.id", + columns = { + @Column(name = "db_type", attrName = "dbType", label = "数据库类型"), + @Column(name = "db_name", attrName = "dbName", label = "数据库名称"), + @Column(name = "db_ip", attrName = "dbIp", label = "数据库IP"), + }), +}, orderBy = "a.create_time DESC" +) +@Data +public class BizExecScript extends DataEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + private Date createTime; // 记录时间 + private String scriptDesc; // 脚本描述 + private String scriptName; // 脚本名称 + private String scriptText; // 脚本内容 + private String dbId; // 执行标识 + private String dataStatus; + private String execResult; + private String updateTime; + + private String dbType; + private String dbName; + private String dbIp; + + + @ExcelFields({ + @ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "唯一标识", attrName = "id", align = Align.CENTER, sort = 20), + @ExcelField(title = "脚本描述", attrName = "scriptDesc", align = Align.CENTER, sort = 30), + @ExcelField(title = "脚本名称", attrName = "scriptName", align = Align.CENTER, sort = 40), + @ExcelField(title = "脚本内容", attrName = "scriptText", align = Align.CENTER, sort = 50), + @ExcelField(title = "执行标识", attrName = "dbId", align = Align.CENTER, sort = 60), + }) + public BizExecScript() { + this(null); + } + + public BizExecScript(String id) { + super(id); + } + + public Date getCreateTime_gte() { + return sqlMap.getWhere().getValue("create_time", QueryType.GTE); + } + + public void setCreateTime_gte(Date createTime) { + sqlMap.getWhere().and("create_time", QueryType.GTE, createTime); + } + + public Date getCreateTime_lte() { + return sqlMap.getWhere().getValue("create_time", QueryType.LTE); + } + + public void setCreateTime_lte(Date createTime) { + sqlMap.getWhere().and("create_time", QueryType.LTE, createTime); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/service/BizExecScriptService.java b/web-api/src/main/java/com/jeesite/modules/biz/service/BizExecScriptService.java new file mode 100644 index 00000000..91507135 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/service/BizExecScriptService.java @@ -0,0 +1,134 @@ +package com.jeesite.modules.biz.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.biz.entity.BizExecScript; +import com.jeesite.modules.biz.dao.BizExecScriptDao; +import com.jeesite.common.service.ServiceException; +import com.jeesite.common.config.Global; +import com.jeesite.common.validator.ValidatorUtils; +import com.jeesite.common.utils.excel.ExcelImport; +import org.springframework.web.multipart.MultipartFile; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; + +/** + * 脚本信息Service + * @author gaoxq + * @version 2026-01-02 + */ +@Service +public class BizExecScriptService extends CrudService { + + /** + * 获取单条数据 + * @param bizExecScript 主键 + */ + @Override + public BizExecScript get(BizExecScript bizExecScript) { + return super.get(bizExecScript); + } + + /** + * 查询分页数据 + * @param bizExecScript 查询条件 + * @param bizExecScript page 分页对象 + */ + @Override + public Page findPage(BizExecScript bizExecScript) { + return super.findPage(bizExecScript); + } + + /** + * 查询列表数据 + * @param bizExecScript 查询条件 + */ + @Override + public List findList(BizExecScript bizExecScript) { + return super.findList(bizExecScript); + } + + /** + * 保存数据(插入或更新) + * @param bizExecScript 数据对象 + */ + @Override + @Transactional + public void save(BizExecScript bizExecScript) { + super.save(bizExecScript); + } + + /** + * 导入数据 + * @param file 导入的数据文件 + */ + @Transactional + public String importData(MultipartFile file) { + if (file == null){ + throw new ServiceException(text("请选择导入的数据文件!")); + } + int successNum = 0; int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + try(ExcelImport ei = new ExcelImport(file, 2, 0)){ + List list = ei.getDataList(BizExecScript.class); + for (BizExecScript bizExecScript : list) { + try{ + ValidatorUtils.validateWithException(bizExecScript); + this.save(bizExecScript); + successNum++; + successMsg.append("
" + successNum + "、编号 " + bizExecScript.getId() + " 导入成功"); + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、编号 " + bizExecScript.getId() + " 导入失败:"; + if (e instanceof ConstraintViolationException){ + ConstraintViolationException cve = (ConstraintViolationException)e; + for (ConstraintViolation violation : cve.getConstraintViolations()) { + msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")"; + } + }else{ + msg += e.getMessage(); + } + failureMsg.append(msg); + logger.error(msg, e); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + failureMsg.append(e.getMessage()); + return failureMsg.toString(); + } + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + }else{ + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + /** + * 更新状态 + * @param bizExecScript 数据对象 + */ + @Override + @Transactional + public void updateStatus(BizExecScript bizExecScript) { + super.updateStatus(bizExecScript); + } + + /** + * 删除数据 + * @param bizExecScript 数据对象 + */ + @Override + @Transactional + public void delete(BizExecScript bizExecScript) { + super.delete(bizExecScript); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/web/BizExecScriptController.java b/web-api/src/main/java/com/jeesite/modules/biz/web/BizExecScriptController.java new file mode 100644 index 00000000..4acb0857 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/web/BizExecScriptController.java @@ -0,0 +1,177 @@ +package com.jeesite.modules.biz.web; + +import java.util.List; + +import com.jeesite.modules.app.utils.MyFileUtils; +import com.jeesite.modules.app.utils.MysqlUtils; +import com.jeesite.modules.app.utils.vDate; +import com.jeesite.modules.biz.entity.BizDbConfig; +import com.jeesite.modules.biz.service.BizDbConfigService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.config.Global; +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.DateUtils; +import com.jeesite.common.utils.excel.ExcelExport; +import com.jeesite.common.utils.excel.annotation.ExcelField.Type; +import org.springframework.web.multipart.MultipartFile; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.biz.entity.BizExecScript; +import com.jeesite.modules.biz.service.BizExecScriptService; + +/** + * 脚本信息Controller + * + * @author gaoxq + * @version 2026-01-02 + */ +@Controller +@RequestMapping(value = "${adminPath}/biz/execScript") +public class BizExecScriptController extends BaseController { + + + @Resource + private BizDbConfigService dbConfigService; + + private final BizExecScriptService bizExecScriptService; + + private static final String EXEC_RUN_PATH = "/ogsapp/script/sql/"; + + public BizExecScriptController(BizExecScriptService bizExecScriptService) { + this.bizExecScriptService = bizExecScriptService; + } + + /** + * 获取数据 + */ + @ModelAttribute + public BizExecScript get(String id, boolean isNewRecord) { + return bizExecScriptService.get(id, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("biz:execScript:view") + @RequestMapping(value = {"list", ""}) + public String list(BizExecScript bizExecScript, Model model) { + model.addAttribute("bizExecScript", bizExecScript); + return "modules/biz/bizExecScriptList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("biz:execScript:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(BizExecScript bizExecScript, HttpServletRequest request, HttpServletResponse response) { + bizExecScript.setPage(new Page<>(request, response)); + Page page = bizExecScriptService.findPage(bizExecScript); + return page; + } + + /** + * 查看编辑表单 + */ + @RequiresPermissions("biz:execScript:view") + @RequestMapping(value = "form") + public String form(BizExecScript bizExecScript, Model model) { + model.addAttribute("bizExecScript", bizExecScript); + return "modules/biz/bizExecScriptForm"; + } + + /** + * 保存数据 + */ + @RequiresPermissions("biz:execScript:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated BizExecScript bizExecScript) { + bizExecScriptService.save(bizExecScript); + return renderResult(Global.TRUE, text("保存脚本信息成功!")); + } + + /** + * 导出数据 + */ + @RequiresPermissions("biz:execScript:view") + @RequestMapping(value = "exportData") + public void exportData(BizExecScript bizExecScript, HttpServletResponse response) { + List list = bizExecScriptService.findList(bizExecScript); + String fileName = "脚本信息" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx"; + try (ExcelExport ee = new ExcelExport("脚本信息", BizExecScript.class)) { + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 下载模板 + */ + @RequiresPermissions("biz:execScript:view") + @RequestMapping(value = "importTemplate") + public void importTemplate(HttpServletResponse response) { + BizExecScript bizExecScript = new BizExecScript(); + List list = ListUtils.newArrayList(bizExecScript); + String fileName = "脚本信息模板.xlsx"; + try (ExcelExport ee = new ExcelExport("脚本信息", BizExecScript.class, Type.IMPORT)) { + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 导入数据 + */ + @ResponseBody + @RequiresPermissions("biz:execScript:edit") + @PostMapping(value = "importData") + public String importData(MultipartFile file) { + try { + String message = bizExecScriptService.importData(file); + return renderResult(Global.TRUE, "posfull:" + message); + } catch (Exception ex) { + return renderResult(Global.FALSE, "posfull:" + ex.getMessage()); + } + } + + /** + * 删除数据 + */ + @RequiresPermissions("biz:execScript:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(BizExecScript bizExecScript) { + BizExecScript execScript = bizExecScriptService.get(bizExecScript); + String scriptName = EXEC_RUN_PATH + execScript.getScriptName(); + MyFileUtils.rmFile(scriptName); + bizExecScriptService.delete(bizExecScript); + return renderResult(Global.TRUE, text("删除脚本信息成功!")); + } + + @RequiresPermissions("biz:execScript:edit") + @RequestMapping(value = "runexec") + @ResponseBody + public String runexec(BizExecScript bizExecScript) { + BizExecScript execScript = bizExecScriptService.get(bizExecScript); + String scriptName = EXEC_RUN_PATH + execScript.getScriptName(); + BizDbConfig dbConfig = dbConfigService.get(execScript.getDbId()); + MyFileUtils.writeFile(scriptName, execScript.getScriptText(), false); + String result = MysqlUtils.getExecScript(dbConfig, execScript.getScriptName()); + execScript.setExecResult(result); + execScript.setUpdateTime(vDate.getNow()); + bizExecScriptService.save(execScript); + return renderResult(Global.TRUE, text("执行脚本信息成功!")); + } +} \ No newline at end of file diff --git a/web-vue/packages/biz/api/biz/execScript.ts b/web-vue/packages/biz/api/biz/execScript.ts new file mode 100644 index 00000000..72a660fd --- /dev/null +++ b/web-vue/packages/biz/api/biz/execScript.ts @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + * @author gaoxq + */ +import { defHttp } from '@jeesite/core/utils/http/axios'; +import { useGlobSetting } from '@jeesite/core/hooks/setting'; +import { BasicModel, Page } from '@jeesite/core/api/model/baseModel'; +import { UploadApiResult } from '@jeesite/core/api/sys/upload'; +import { UploadFileParams } from '@jeesite/types/axios'; +import { AxiosProgressEvent } from 'axios'; + +const { ctxPath, adminPath } = useGlobSetting(); + +export interface BizExecScript extends BasicModel { + createTime?: string; // 记录时间 + scriptDesc?: string; // 脚本描述 + scriptName?: string; // 脚本名称 + scriptText?: string; // 脚本内容 + dbId?: string; // 执行标识 + dataStatus?: string; + execResult?: string; + updateTime?: string; +} + +export const bizExecScriptList = (params?: BizExecScript | any) => + defHttp.get({ url: adminPath + '/biz/execScript/list', params }); + +export const bizExecScriptListData = (params?: BizExecScript | any) => + defHttp.post>({ url: adminPath + '/biz/execScript/listData', params }); + +export const bizExecScriptForm = (params?: BizExecScript | any) => + defHttp.get({ url: adminPath + '/biz/execScript/form', params }); + +export const bizExecScriptSave = (params?: any, data?: BizExecScript | any) => + defHttp.postJson({ url: adminPath + '/biz/execScript/save', params, data }); + +export const bizExecScriptImportData = ( + params: UploadFileParams, + onUploadProgress: (progressEvent: AxiosProgressEvent) => void, +) => + defHttp.uploadFile( + { + url: ctxPath + adminPath + '/biz/execScript/importData', + onUploadProgress, + }, + params, + ); + +export const bizExecScriptDelete = (params?: BizExecScript | any) => + defHttp.get({ url: adminPath + '/biz/execScript/delete', params }); + +export const bizExecScriptRunexec = (params?: BizExecScript | any) => + defHttp.get({ url: adminPath + '/biz/execScript/runexec', params }); diff --git a/web-vue/packages/biz/views/biz/execScript/form.vue b/web-vue/packages/biz/views/biz/execScript/form.vue new file mode 100644 index 00000000..537f5afa --- /dev/null +++ b/web-vue/packages/biz/views/biz/execScript/form.vue @@ -0,0 +1,131 @@ + + + diff --git a/web-vue/packages/biz/views/biz/execScript/formImport.vue b/web-vue/packages/biz/views/biz/execScript/formImport.vue new file mode 100644 index 00000000..7306566e --- /dev/null +++ b/web-vue/packages/biz/views/biz/execScript/formImport.vue @@ -0,0 +1,103 @@ + + + diff --git a/web-vue/packages/biz/views/biz/execScript/list.vue b/web-vue/packages/biz/views/biz/execScript/list.vue new file mode 100644 index 00000000..0d74d055 --- /dev/null +++ b/web-vue/packages/biz/views/biz/execScript/list.vue @@ -0,0 +1,243 @@ + + +