Unverified Commit cab944cb authored by JPengCheng's avatar JPengCheng Committed by GitHub

[Feature][admin,web] Add import and export tasks json (#749)

parent c12cdbd3
...@@ -30,6 +30,7 @@ import com.fasterxml.jackson.databind.JsonNode; ...@@ -30,6 +30,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -228,5 +229,30 @@ public class TaskController { ...@@ -228,5 +229,30 @@ public class TaskController {
public Result getTaskAPIAddress() { public Result getTaskAPIAddress() {
return Result.succeed(taskService.getTaskAPIAddress(), "重启成功"); return Result.succeed(taskService.getTaskAPIAddress(), "重启成功");
} }
/**
* 导出json
*/
@GetMapping(value = "/exportJsonByTaskId")
public Result exportJsonByTaskId(@RequestParam Integer id) {
return Result.succeed(taskService.exportJsonByTaskId(id),"获取成功");
}
/**
* 导出json数组
*/
@PostMapping(value = "/exportJsonByTaskIds")
public Result exportJsonByTaskIds(@RequestBody JsonNode para) {
return Result.succeed(taskService.exportJsonByTaskIds(para),"获取成功");
}
/**
* json文件上传 导入task
*/
@PostMapping(value="/uploadTaskJson")
public Result uploadTaskJson(@RequestParam("file") MultipartFile file) throws Exception {
return taskService.uploadTaskJson(file);
}
} }
...@@ -45,4 +45,15 @@ public class Catalogue extends SuperEntity { ...@@ -45,4 +45,15 @@ public class Catalogue extends SuperEntity {
private Integer parentId; private Integer parentId;
private Boolean isLeaf; private Boolean isLeaf;
public Catalogue() {
}
public Catalogue(String name, Integer taskId, String type, Integer parentId, Boolean isLeaf) {
this.setName(name);
this.taskId = taskId;
this.type = type;
this.parentId = parentId;
this.isLeaf = isLeaf;
}
} }
...@@ -27,7 +27,9 @@ import com.dlink.assertion.Asserts; ...@@ -27,7 +27,9 @@ import com.dlink.assertion.Asserts;
import com.dlink.db.model.SuperEntity; import com.dlink.db.model.SuperEntity;
import com.dlink.job.JobConfig; import com.dlink.job.JobConfig;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
...@@ -104,6 +106,23 @@ public class Task extends SuperEntity { ...@@ -104,6 +106,23 @@ public class Task extends SuperEntity {
@TableField(exist = false) @TableField(exist = false)
private List<Map<String, String>> config = new ArrayList<>(); private List<Map<String, String>> config = new ArrayList<>();
@TableField(exist = false)
private String path;
@TableField(exist = false)
private String jarName;
@TableField(exist = false)
private String clusterConfigurationName;
@TableField(exist = false)
private String databaseName;
@TableField(exist = false)
private String envName;
@TableField(exist = false)
private String alertGroupName;
public List<Map<String, String>> parseConfig() { public List<Map<String, String>> parseConfig() {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
...@@ -135,4 +154,30 @@ public class Task extends SuperEntity { ...@@ -135,4 +154,30 @@ public class Task extends SuperEntity {
alias, fg, sts, batchModel, checkPoint, parallelism, savePointStrategy, savePointPath, map); alias, fg, sts, batchModel, checkPoint, parallelism, savePointStrategy, savePointPath, map);
} }
public JsonNode parseJsonNode(){
ObjectMapper mapper = new ObjectMapper();
return parseJsonNode(mapper);
}
public JsonNode parseJsonNode(ObjectMapper mapper){
JsonNode jsonNode = mapper.createObjectNode();
((ObjectNode)jsonNode).put("name",this.getName());
((ObjectNode)jsonNode).put("alias",this.alias);
((ObjectNode)jsonNode).put("dialect",this.dialect);
((ObjectNode)jsonNode).put("type",this.type);
((ObjectNode)jsonNode).put("statement",this.statement);
((ObjectNode)jsonNode).put("checkPoint",this.checkPoint);
((ObjectNode)jsonNode).put("savePointStrategy",this.savePointStrategy);
((ObjectNode)jsonNode).put("savePointPath",this.savePointPath);
((ObjectNode)jsonNode).put("parallelism",this.parallelism);
((ObjectNode)jsonNode).put("fragment",this.fragment);
((ObjectNode)jsonNode).put("statementSet",this.statementSet);
((ObjectNode)jsonNode).put("batchModel",this.batchModel);
((ObjectNode)jsonNode).put("clusterName",this.clusterName);
((ObjectNode)jsonNode).put("configJson",this.configJson);
((ObjectNode)jsonNode).put("note",this.note);
((ObjectNode)jsonNode).put("step",this.step);
((ObjectNode)jsonNode).put("enabled",this.getEnabled());
return jsonNode;
}
} }
...@@ -49,4 +49,6 @@ public interface CatalogueService extends ISuperService<Catalogue> { ...@@ -49,4 +49,6 @@ public interface CatalogueService extends ISuperService<Catalogue> {
boolean moveCatalogue(Integer id, Integer parentId); boolean moveCatalogue(Integer id, Integer parentId);
boolean copyTask(Catalogue catalogue); boolean copyTask(Catalogue catalogue);
Integer addDependCatalogue(String[] catalogueNames);
} }
...@@ -29,6 +29,8 @@ import com.dlink.model.JobInfoDetail; ...@@ -29,6 +29,8 @@ import com.dlink.model.JobInfoDetail;
import com.dlink.model.JobInstance; import com.dlink.model.JobInstance;
import com.dlink.model.Task; import com.dlink.model.Task;
import com.dlink.result.SqlExplainResult; import com.dlink.result.SqlExplainResult;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
...@@ -85,4 +87,10 @@ public interface TaskService extends ISuperService<Task> { ...@@ -85,4 +87,10 @@ public interface TaskService extends ISuperService<Task> {
Result rollbackTask(TaskRollbackVersionDTO dto); Result rollbackTask(TaskRollbackVersionDTO dto);
Integer queryAllSizeByName(String name); Integer queryAllSizeByName(String name);
String exportJsonByTaskId(Integer taskId);
String exportJsonByTaskIds(JsonNode para);
Result uploadTaskJson(MultipartFile file) throws Exception;
} }
...@@ -23,7 +23,9 @@ package com.dlink.service.impl; ...@@ -23,7 +23,9 @@ package com.dlink.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dlink.assertion.Asserts;
import com.dlink.db.service.impl.SuperServiceImpl; import com.dlink.db.service.impl.SuperServiceImpl;
import com.dlink.dto.CatalogueTaskDTO; import com.dlink.dto.CatalogueTaskDTO;
import com.dlink.mapper.CatalogueMapper; import com.dlink.mapper.CatalogueMapper;
...@@ -34,6 +36,7 @@ import com.dlink.model.Task; ...@@ -34,6 +36,7 @@ import com.dlink.model.Task;
import com.dlink.service.CatalogueService; import com.dlink.service.CatalogueService;
import com.dlink.service.StatementService; import com.dlink.service.StatementService;
import com.dlink.service.TaskService; import com.dlink.service.TaskService;
import org.apache.kafka.common.internals.Topic;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
...@@ -192,4 +195,24 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata ...@@ -192,4 +195,24 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata
return this.save(catalogue); return this.save(catalogue);
} }
@Override
public Integer addDependCatalogue(String[] catalogueNames){
Integer parentId = 0;
for (int i = 0; i < catalogueNames.length - 1; i++) {
String catalogueName = catalogueNames[i];
Catalogue catalogue = getOne(new QueryWrapper<Catalogue>().eq("name", catalogueName).eq("parent_id", parentId).last(" limit 1"));
if (Asserts.isNotNull(catalogue)) {
parentId = catalogue.getId();
continue;
}
catalogue = new Catalogue();
catalogue.setName(catalogueName);
catalogue.setParentId(parentId);
catalogue.setIsLeaf(false);
this.save(catalogue);
parentId = catalogue.getId();
}
return parentId;
}
} }
...@@ -22,8 +22,12 @@ package com.dlink.service.impl; ...@@ -22,8 +22,12 @@ package com.dlink.service.impl;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
...@@ -38,8 +42,14 @@ import java.util.stream.Collectors; ...@@ -38,8 +42,14 @@ import java.util.stream.Collectors;
import javax.annotation.Resource; import javax.annotation.Resource;
import com.dlink.model.*;
import com.dlink.service.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
...@@ -77,42 +87,13 @@ import com.dlink.job.JobResult; ...@@ -77,42 +87,13 @@ import com.dlink.job.JobResult;
import com.dlink.mapper.TaskMapper; import com.dlink.mapper.TaskMapper;
import com.dlink.metadata.driver.Driver; import com.dlink.metadata.driver.Driver;
import com.dlink.metadata.result.JdbcSelectResult; import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.AlertGroup;
import com.dlink.model.AlertHistory;
import com.dlink.model.AlertInstance;
import com.dlink.model.Cluster;
import com.dlink.model.DataBase;
import com.dlink.model.History;
import com.dlink.model.Jar;
import com.dlink.model.JobHistory;
import com.dlink.model.JobInfoDetail;
import com.dlink.model.JobInstance;
import com.dlink.model.JobLifeCycle;
import com.dlink.model.JobStatus;
import com.dlink.model.Savepoints;
import com.dlink.model.Statement;
import com.dlink.model.SystemConfiguration;
import com.dlink.model.Task;
import com.dlink.model.TaskVersion;
import com.dlink.result.SqlExplainResult; import com.dlink.result.SqlExplainResult;
import com.dlink.service.AlertGroupService;
import com.dlink.service.AlertHistoryService;
import com.dlink.service.ClusterConfigurationService;
import com.dlink.service.ClusterService;
import com.dlink.service.DataBaseService;
import com.dlink.service.HistoryService;
import com.dlink.service.JarService;
import com.dlink.service.JobHistoryService;
import com.dlink.service.JobInstanceService;
import com.dlink.service.SavepointsService;
import com.dlink.service.StatementService;
import com.dlink.service.TaskService;
import com.dlink.service.TaskVersionService;
import com.dlink.utils.CustomStringJavaCompiler; import com.dlink.utils.CustomStringJavaCompiler;
import com.dlink.utils.JSONUtil; import com.dlink.utils.JSONUtil;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import org.springframework.web.multipart.MultipartFile;
/** /**
* 任务 服务实现类 * 任务 服务实现类
...@@ -145,6 +126,9 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -145,6 +126,9 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
private AlertHistoryService alertHistoryService; private AlertHistoryService alertHistoryService;
@Autowired @Autowired
private HistoryService historyService; private HistoryService historyService;
@Autowired
@Lazy
private CatalogueService catalogueService;
@Resource @Resource
private TaskVersionService taskVersionService; private TaskVersionService taskVersionService;
...@@ -827,6 +811,201 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -827,6 +811,201 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
return baseMapper.queryAllSizeByName(name); return baseMapper.queryAllSizeByName(name);
} }
@Override
public String exportJsonByTaskId(Integer taskId) {
ObjectMapper mapper = new ObjectMapper();
Task task = getTaskInfoById(taskId);
if (Asserts.isNotNull(task.getClusterId())) {
Cluster cluster = clusterService.getById(task.getClusterId());
if (Asserts.isNotNull(cluster)) {
task.setClusterName(cluster.getName());
}
}
// path
JsonNode jsonNode = task.parseJsonNode(mapper);
((ObjectNode)jsonNode).put("path",getTaskPathByTaskId(taskId));
// clusterConfigurationName
if (Asserts.isNotNull(task.getClusterConfigurationId())) {
ClusterConfiguration clusterConfiguration = clusterConfigurationService.getById(task.getClusterConfigurationId());
((ObjectNode) jsonNode).put("clusterConfigurationName", Asserts.isNotNull(clusterConfiguration) ? clusterConfiguration.getName() : null);
}
// databaseName
if (Asserts.isNotNull(task.getDatabaseId())) {
DataBase dataBase = dataBaseService.getById(task.getDatabaseId());
((ObjectNode) jsonNode).put("databaseName", Asserts.isNotNull(dataBase) ? dataBase.getName() : null);
}
// jarName
if (Asserts.isNotNull(task.getJarId())) {
Jar jar = jarService.getById(task.getJarId());
((ObjectNode) jsonNode).put("jarName", Asserts.isNotNull(jar) ? jar.getName() : null);
}
// envName
if (Asserts.isNotNull(task.getEnvId())) {
Task envTask = getById(task.getEnvId());
((ObjectNode) jsonNode).put("envName", Asserts.isNotNull(envTask) ? envTask.getName() : null);
}
// alertGroupName
if (Asserts.isNotNull(task.getAlertGroupId())) {
AlertGroup alertGroup = alertGroupService.getById(task.getAlertGroupId());
((ObjectNode) jsonNode).put("alertGroupName", Asserts.isNotNull(alertGroup) ? alertGroup.getName() : null);
}
return jsonNode.toString();
}
@Override
public String exportJsonByTaskIds(JsonNode para) {
StringBuilder tasksJson = new StringBuilder();
tasksJson.append("[");
for (final JsonNode item : para.get("taskIds")) {
Integer id = item.asInt();
tasksJson.append(exportJsonByTaskId(id)+",");
}
tasksJson.deleteCharAt(tasksJson.length()-1);
tasksJson.append("]");
return tasksJson.toString();
}
@Override
public Result uploadTaskJson(MultipartFile file) throws Exception {
if (file == null || file.getSize() == 0) {
return Result.failed("上传失败,找不到文件");
}
String fileName = file.getOriginalFilename().split("\\.")[0];
if (file.isEmpty() || file.getSize() <= 0 || fileName == null || "".equals(fileName)) {
return Result.failed("传入的文件数据为空");
}
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(getStrByJsonFile(file));
return buildTaskByJsonNode(jsonNode, mapper);
}
public Result buildTaskByJsonNode(JsonNode jsonNode,ObjectMapper mapper) throws JsonProcessingException {
List<JsonNode> jsonNodes = new ArrayList<>();
if (jsonNode.isArray()) {
for(JsonNode a: jsonNode){
/*if(a.get("dialect").asText().equals("FlinkSqlEnv")){
jsonNodes.add(0,a);
}else{
jsonNodes.add(a);
}*/
jsonNodes.add(a);
}
} else {
jsonNodes.add(jsonNode);
}
int errorNumber = 0;
List<Task> tasks = new ArrayList<>();
for(JsonNode json : jsonNodes){
Task task = mapper.treeToValue(json, Task.class);
if(Asserts.isNotNull(task.getClusterName())){
Cluster cluster = clusterService.getOne(new QueryWrapper<Cluster>().eq("name", task.getClusterName()));
if(Asserts.isNotNull(cluster)){
task.setClusterId(cluster.getId());
}
}
if(Asserts.isNotNull(task.getClusterConfigurationName())){
ClusterConfiguration clusterConfiguration = clusterConfigurationService
.getOne(new QueryWrapper<ClusterConfiguration>().eq("name", task.getClusterConfigurationName()));
if(Asserts.isNotNull(clusterConfiguration)){
task.setClusterConfigurationId(clusterConfiguration.getId());
}
}
if(Asserts.isNotNull(task.getDatabaseName())){
DataBase dataBase = dataBaseService.getOne(new QueryWrapper<DataBase>().eq("name", task.getDatabaseName()));
if(Asserts.isNotNull(dataBase)){
task.setDatabaseId(dataBase.getId());
}
}
if(Asserts.isNotNull(task.getJarName())){
Jar jar = jarService.getOne(new QueryWrapper<Jar>().eq("name", task.getJarName()));
if(Asserts.isNotNull(jar)){
task.setJarId(jar.getId());
}
}
/*if(Asserts.isNotNull(task.getEnvName())){
Task task1 = getOne(new QueryWrapper<Task>().eq("name", task.getEnvName()));
if(Asserts.isNotNull(task1)){
task.setEnvId(task1.getId());
}
}*/
if(Asserts.isNotNull(task.getAlertGroupName())){
AlertGroup alertGroup = alertGroupService.getOne(new QueryWrapper<AlertGroup>().eq("name", task.getAlertGroupName()));
if(Asserts.isNotNull(alertGroup)){
task.setAlertGroupId(alertGroup.getId());
}
}
// 路径生成
String[] paths = task.getPath().split("/");
Integer parentId = catalogueService.addDependCatalogue(paths);
Task task1 = getOne(new QueryWrapper<Task>().eq("name", task.getName()));
if(Asserts.isNotNull(task1)){
errorNumber++;
continue;
}
Integer step = task.getStep();
this.saveOrUpdateTask(task);
if (!JobLifeCycle.CREATE.getValue().equals(step)){
task.setStep(step);
updateById(task);
}
if(Asserts.isNotNull(task.getEnvName())){
tasks.add(task);
}
Catalogue catalogue = new Catalogue(task.getAlias(),task.getId(),task.getDialect(),parentId,true);
catalogueService.saveOrUpdate(catalogue);
}
for(Task task: tasks){
Task task1 = getOne(new QueryWrapper<Task>().eq("name", task.getEnvName()));
if(Asserts.isNotNull(task1)){
task.setEnvId(task1.getId());
this.saveOrUpdateTask(task);
}
}
if (errorNumber > 0 && errorNumber == jsonNodes.size()) {
return Result.failed("一共" + jsonNodes.size() + "个作业,全部导入失败");
} else if(errorNumber > 0) {
return Result.failed("一共" + jsonNodes.size() + "个作业,其中成功导入" + (jsonNode.size() - errorNumber) + "个,失败" + errorNumber + "个");
}
return Result.succeed("成功导入" + jsonNodes.size() + "个作业");
}
public String getStrByJsonFile(MultipartFile jsonFile){
String jsonStr = "";
try {
Reader reader = new InputStreamReader(jsonFile.getInputStream(), StandardCharsets.UTF_8);
int ch = 0;
StringBuffer sb = new StringBuffer();
while ((ch = reader.read()) != -1) {
sb.append((char) ch);
}
reader.close();
jsonStr = sb.toString();
return jsonStr;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public String getTaskPathByTaskId(Integer taskId){
StringBuilder path = new StringBuilder();
path.append(getById(taskId).getAlias());
Catalogue catalogue = catalogueService.getOne(new QueryWrapper<Catalogue>().eq("task_id", taskId));
if(Asserts.isNull(catalogue)){
return path.toString();
}
int catalogueId = catalogue.getParentId();
do {
catalogue = catalogueService.getById(catalogueId);
if(Asserts.isNull(catalogue)){
return path.toString();
}
path.insert(0, catalogue.getName() + "/");
catalogueId = catalogue.getParentId();
} while (catalogueId != 0);
return path.toString();
}
private String getDuration(long jobStartTimeMills, long jobEndTimeMills) { private String getDuration(long jobStartTimeMills, long jobEndTimeMills) {
Instant startTime = Instant.ofEpochMilli(jobStartTimeMills); Instant startTime = Instant.ofEpochMilli(jobStartTimeMills);
......
...@@ -208,6 +208,21 @@ export const handleOption = async (url:string,title:string,param:any) => { ...@@ -208,6 +208,21 @@ export const handleOption = async (url:string,title:string,param:any) => {
} }
}; };
export const handleData = async (url:string,id:any) => {
try {
const {code,datas,msg} = await getData(url,id);
if(code == CODE.SUCCESS){
return datas;
}else{
message.warn(msg);
return false;
}
} catch (error) {
message.error('获取失败,请重试');
return false;
}
};
export const handleInfo = async (url:string,id:number) => { export const handleInfo = async (url:string,id:number) => {
try { try {
const {datas} = await getInfoById(url,id); const {datas} = await getInfoById(url,id);
......
...@@ -20,14 +20,21 @@ ...@@ -20,14 +20,21 @@
import React, {useEffect, useState, Key} from "react"; import React, {useEffect, useState, Key} from "react";
import {connect} from "umi"; import {connect} from "umi";
import {DownOutlined, SwitcherOutlined, FolderAddOutlined} from "@ant-design/icons"; import {DownOutlined, SwitcherOutlined, FolderAddOutlined, UploadOutlined, DownloadOutlined} from "@ant-design/icons";
import {Tree, Menu, Empty, Button, message, Modal, Tooltip, Row, Col, Input} from 'antd'; import {Tree, Menu, Empty, Button, message, Modal, Tooltip, Row, Col, Input, Upload} from 'antd';
import type { UploadProps } from 'antd';
import {getCatalogueTreeData} from "@/pages/DataStudio/service"; import {getCatalogueTreeData} from "@/pages/DataStudio/service";
import {convertToTreeData, getTreeNodeByKey, TreeDataNode} from "@/components/Studio/StudioTree/Function"; import {convertToTreeData, getTreeNodeByKey, TreeDataNode} from "@/components/Studio/StudioTree/Function";
import style from "./index.less"; import style from "./index.less";
import {StateType} from "@/pages/DataStudio/model"; import {StateType} from "@/pages/DataStudio/model";
import { import {
getInfoById, handleAddOrUpdate, handleAddOrUpdateWithResult, handleOption, handleRemoveById, handleSubmit handleData,
getInfoById,
handleAddOrUpdate,
handleAddOrUpdateWithResult,
handleOption,
handleRemoveById,
handleSubmit, CODE, postAll,
} from "@/components/Common/crud"; } from "@/components/Common/crud";
import UpdateCatalogueForm from './components/UpdateCatalogueForm'; import UpdateCatalogueForm from './components/UpdateCatalogueForm';
import SimpleTaskForm from "@/components/Studio/StudioTree/components/SimpleTaskForm"; import SimpleTaskForm from "@/components/Studio/StudioTree/components/SimpleTaskForm";
...@@ -104,6 +111,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -104,6 +111,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
const [autoExpandParent, setAutoExpandParent] = useState(true); const [autoExpandParent, setAutoExpandParent] = useState(true);
const [cutId, setCutId] = useState<number | undefined>(undefined); const [cutId, setCutId] = useState<number | undefined>(undefined);
const [exportTaskIds, setExportTaskIds] = useState<any[]>([]);
const getTreeData = async () => { const getTreeData = async () => {
const result = await getCatalogueTreeData(); const result = await getCatalogueTreeData();
...@@ -123,6 +131,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -123,6 +131,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
//默认展开所有 //默认展开所有
setExpandedKeys(expendList || []); setExpandedKeys(expendList || []);
setDefaultExpandedKeys(expendList || []); setDefaultExpandedKeys(expendList || []);
setExportTaskIds([]);
}; };
const onChange = (e: any) => { const onChange = (e: any) => {
...@@ -192,6 +201,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -192,6 +201,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
toPaste(rightClickNode); toPaste(rightClickNode);
} else if (key == 'Copy') { } else if (key == 'Copy') {
toCopy(rightClickNode); toCopy(rightClickNode);
}else if (key == 'ExportJson') {
toExportJson(rightClickNode);
} }
}; };
...@@ -340,6 +351,54 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -340,6 +351,54 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
} }
}; };
const toExportJson = async (node: TreeDataNode | undefined) => {
let taskId = node?.taskId;
const datas = await handleData('/api/task/exportJsonByTaskId',{id:taskId});
if (datas) {
let data = JSON.parse(datas);
saveJSON(data,data.alias);
message.success('导出json成功');
}
};
const toExportSelectedTaskJson = async () => {
if (exportTaskIds.length <= 0) {
message.warn("请先选择要导出的作业");
} else {
try {
const {code, datas, msg} = await postAll('/api/task/exportJsonByTaskIds', {taskIds:exportTaskIds});
if (code == CODE.SUCCESS) {
saveJSON(datas);
message.success('导出json成功');
} else {
message.warn(msg);
}
} catch (error) {
message.error('获取失败,请重试');
}
}
}
const saveJSON = (data:any, filename?:any) => {
if (!data) {
message.error("保存的json数据为空");
return;
}
if (!filename)
filename = new Date().toLocaleDateString().replaceAll("/", "-");
if (typeof data === 'object') {
data = JSON.stringify(data, undefined, 4)
}
let blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename + '.json'
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
const createTask = (node: TreeDataNode | undefined) => { const createTask = (node: TreeDataNode | undefined) => {
if (!node?.isLeaf) { if (!node?.isLeaf) {
handleUpdateTaskModalVisible(true); handleUpdateTaskModalVisible(true);
...@@ -384,6 +443,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -384,6 +443,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
menuItems = (<> menuItems = (<>
<Menu.Item key='Open'>{'打开'}</Menu.Item> <Menu.Item key='Open'>{'打开'}</Menu.Item>
<Menu.Item key='Submit'>{'异步提交'}</Menu.Item> <Menu.Item key='Submit'>{'异步提交'}</Menu.Item>
<Menu.Item key='ExportJson'>{'导出Json'}</Menu.Item>
<Menu.Item key='Rename'>{'重命名'}</Menu.Item> <Menu.Item key='Rename'>{'重命名'}</Menu.Item>
<Menu.Item key='Copy'>{'复制'}</Menu.Item> <Menu.Item key='Copy'>{'复制'}</Menu.Item>
<Menu.Item key='Cut'>{'剪切'}</Menu.Item> <Menu.Item key='Cut'>{'剪切'}</Menu.Item>
...@@ -462,6 +522,13 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -462,6 +522,13 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
}); });
toOpen(e.node); toOpen(e.node);
} }
let taskIds = [];
for (let i = 0; i < e.selectedNodes.length; i++) {
if(e.selectedNodes[i].isLeaf){
taskIds.push(e.selectedNodes[i].taskId);
}
}
setExportTaskIds(taskIds);
}; };
const offExpandAll = () => { const offExpandAll = () => {
...@@ -517,6 +584,27 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -517,6 +584,27 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
}; };
}); });
const uProps: UploadProps = {
name: 'file',
action: '/api/task/uploadTaskJson',
accept: 'application/json',
headers: {
authorization: 'authorization-text',
},
onChange(info) {
if (info.file.status === 'done') {
if(info.file.response.code == CODE.SUCCESS){
message.success(info.file.response.msg);
}else{
message.warn(info.file.response.msg);
}
getTreeData();
} else if (info.file.status === 'error') {
message.error(`${info.file.name} 上传失败`);
}
},
};
return ( return (
<div className={style.tree_div}> <div className={style.tree_div}>
<Row> <Row>
...@@ -535,6 +623,21 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -535,6 +623,21 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
onClick={offExpandAll} onClick={offExpandAll}
/> />
</Tooltip> </Tooltip>
<Tooltip title="导出json">
<Button
type="text"
icon={<DownloadOutlined />}
onClick={toExportSelectedTaskJson}
/>
</Tooltip>
<Upload {...uProps}>
<Tooltip title="导入json">
<Button
type="text"
icon={<UploadOutlined/>}
/>
</Tooltip>
</Upload>
</Col> </Col>
</Row> </Row>
<Search style={{marginBottom: 8}} placeholder="Search" onChange={onChange} allowClear={true}/> <Search style={{marginBottom: 8}} placeholder="Search" onChange={onChange} allowClear={true}/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment