feat: 增加任务模板的增删改查
This commit is contained in:
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -3,7 +3,6 @@
|
|||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/leopard-core/leopard-core.iml" filepath="$PROJECT_DIR$/leopard-core/leopard-core.iml" />
|
<module fileurl="file://$PROJECT_DIR$/leopard-core/leopard-core.iml" filepath="$PROJECT_DIR$/leopard-core/leopard-core.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/leopard-server/leopard-server.iml" filepath="$PROJECT_DIR$/leopard-server/leopard-server.iml" />
|
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -2,6 +2,7 @@ package com.lanyuanxiaoyao.leopard.server.controller;
|
|||||||
|
|
||||||
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
||||||
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||||
import com.lanyuanxiaoyao.leopard.server.service.StockService;
|
import com.lanyuanxiaoyao.leopard.server.service.StockService;
|
||||||
import com.lanyuanxiaoyao.service.template.controller.GlobalResponse;
|
import com.lanyuanxiaoyao.service.template.controller.GlobalResponse;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -106,6 +107,11 @@ public class CommonOptionsController {
|
|||||||
new Option("已退市", false)
|
new Option("已退市", false)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
case "task_template_type" -> GlobalResponse.responseSuccess(
|
||||||
|
Arrays.stream(TaskTemplate.Type.values())
|
||||||
|
.map(type -> new Option(type.getChineseName(), type.name()))
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
default -> GlobalResponse.responseSuccess(List.of());
|
default -> GlobalResponse.responseSuccess(List.of());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -132,6 +138,12 @@ public class CommonOptionsController {
|
|||||||
.toList(),
|
.toList(),
|
||||||
field
|
field
|
||||||
));
|
));
|
||||||
|
case "task_template_type" -> GlobalResponse.responseSuccess(buildMapping(
|
||||||
|
Arrays.stream(TaskTemplate.Type.values())
|
||||||
|
.map(type -> new Mapping(type.name(), type.getChineseName()))
|
||||||
|
.toList(),
|
||||||
|
field
|
||||||
|
));
|
||||||
default -> GlobalResponse.responseSuccess(Map.of());
|
default -> GlobalResponse.responseSuccess(Map.of());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.lanyuanxiaoyao.leopard.server.controller;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.templates.ClassTaskTemplate;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.service.TaskTemplateService;
|
||||||
|
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("task_template")
|
||||||
|
public class TaskTemplateController extends SimpleControllerSupport<TaskTemplate, TaskTemplateController.Item, TaskTemplateController.Item, TaskTemplateController.Item> {
|
||||||
|
public TaskTemplateController(TaskTemplateService service) {
|
||||||
|
super(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<Item, TaskTemplate> saveItemMapper() {
|
||||||
|
return item -> {
|
||||||
|
return switch (item.type) {
|
||||||
|
case CLASS -> {
|
||||||
|
var template = new ClassTaskTemplate();
|
||||||
|
template.setName(item.name());
|
||||||
|
template.setDescription(item.description());
|
||||||
|
template.setClazz(item.clazz());
|
||||||
|
yield template;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Item convert(TaskTemplate template) {
|
||||||
|
return switch (template.getType()) {
|
||||||
|
case CLASS -> {
|
||||||
|
ClassTaskTemplate classTaskTemplate = (ClassTaskTemplate) template;
|
||||||
|
yield new Item(classTaskTemplate.getId(), classTaskTemplate.getName(), classTaskTemplate.getDescription(), classTaskTemplate.getType(), classTaskTemplate.getClazz());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<TaskTemplate, Item> listItemMapper() {
|
||||||
|
return this::convert;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<TaskTemplate, Item> detailItemMapper() {
|
||||||
|
return this::convert;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Item(
|
||||||
|
Long id,
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
TaskTemplate.Type type,
|
||||||
|
String clazz
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.lanyuanxiaoyao.leopard.server.entity;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.Constants;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.base.SimpleEnum;
|
||||||
|
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.EntityListeners;
|
||||||
|
import jakarta.persistence.Inheritance;
|
||||||
|
import jakarta.persistence.InheritanceType;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
import org.hibernate.annotations.DynamicInsert;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
import org.hibernate.annotations.SoftDelete;
|
||||||
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@FieldNameConstants
|
||||||
|
@Entity
|
||||||
|
@SoftDelete
|
||||||
|
@DynamicUpdate
|
||||||
|
@DynamicInsert
|
||||||
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
|
@Table(name = Constants.DATABASE_PREFIX + "task_template")
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
public abstract class TaskTemplate extends SimpleEntity {
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
@Column(nullable = false, length = 500)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public abstract Type getType();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum Type implements SimpleEnum {
|
||||||
|
CLASS("类任务");
|
||||||
|
|
||||||
|
private final String chineseName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.lanyuanxiaoyao.leopard.server.entity.templates;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.Constants;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.EntityListeners;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
import org.hibernate.annotations.DynamicInsert;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
import org.hibernate.annotations.SoftDelete;
|
||||||
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@FieldNameConstants
|
||||||
|
@Entity
|
||||||
|
@SoftDelete
|
||||||
|
@DynamicUpdate
|
||||||
|
@DynamicInsert
|
||||||
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
|
@Table(name = Constants.DATABASE_PREFIX + "task_template_class")
|
||||||
|
public class ClassTaskTemplate extends TaskTemplate {
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String clazz;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.CLASS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.lanyuanxiaoyao.leopard.server.repository;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||||
|
import com.lanyuanxiaoyao.service.template.repository.SimpleRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface TaskTemplateRepository extends SimpleRepository<TaskTemplate> {
|
||||||
|
}
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
package com.lanyuanxiaoyao.leopard.server.service;
|
package com.lanyuanxiaoyao.leopard.server.service;
|
||||||
|
|
||||||
import cn.hutool.core.util.EnumUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
||||||
import com.lanyuanxiaoyao.leopard.server.repository.StockRepository;
|
import com.lanyuanxiaoyao.leopard.server.repository.StockRepository;
|
||||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -18,58 +15,13 @@ import org.springframework.stereotype.Service;
|
|||||||
@Service
|
@Service
|
||||||
public class StockService extends SimpleServiceSupport<Stock> {
|
public class StockService extends SimpleServiceSupport<Stock> {
|
||||||
private final StockRepository stockRepository;
|
private final StockRepository stockRepository;
|
||||||
private final TuShareService tuShareService;
|
|
||||||
private final TaskService taskService;
|
|
||||||
|
|
||||||
public StockService(StockRepository repository, TuShareService tuShareService, TaskService taskService) {
|
public StockService(StockRepository repository) {
|
||||||
super(repository);
|
super(repository);
|
||||||
this.stockRepository = repository;
|
this.stockRepository = repository;
|
||||||
this.tuShareService = tuShareService;
|
|
||||||
this.taskService = taskService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> findDistinctIndustries() {
|
public List<String> findDistinctIndustries() {
|
||||||
return stockRepository.findDistinctIndustries();
|
return stockRepository.findDistinctIndustries();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
|
||||||
taskService.startTask(
|
|
||||||
"股票列表刷新",
|
|
||||||
"股票列表刷新",
|
|
||||||
() -> {
|
|
||||||
var stocks = list();
|
|
||||||
var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock));
|
|
||||||
tuShareService.stockList()
|
|
||||||
.data()
|
|
||||||
.items()
|
|
||||||
.forEach(item -> {
|
|
||||||
var code = item.get(0);
|
|
||||||
var name = item.get(1);
|
|
||||||
var fullname = item.get(2);
|
|
||||||
var market = EnumUtil.fromString(Stock.Market.class, item.get(3));
|
|
||||||
var industry = item.get(4);
|
|
||||||
var listed = StrUtil.equals("L", item.get(5));
|
|
||||||
if (stocksMap.containsKey(code)) {
|
|
||||||
var stock = stocksMap.get(code);
|
|
||||||
stock.setName(name);
|
|
||||||
stock.setFullname(fullname);
|
|
||||||
stock.setMarket(market);
|
|
||||||
stock.setIndustry(industry);
|
|
||||||
stock.setListed(listed);
|
|
||||||
} else {
|
|
||||||
var stock = new Stock();
|
|
||||||
stock.setCode(code);
|
|
||||||
stock.setName(name);
|
|
||||||
stock.setFullname(fullname);
|
|
||||||
stock.setMarket(market);
|
|
||||||
stock.setIndustry(industry);
|
|
||||||
stock.setListed(listed);
|
|
||||||
stocks.add(stock);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
repository.saveOrUpdateAllByNotNullProperties(stocks);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
package com.lanyuanxiaoyao.leopard.server.service;
|
package com.lanyuanxiaoyao.leopard.server.service;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
||||||
import com.lanyuanxiaoyao.leopard.server.repository.TaskRepository;
|
import com.lanyuanxiaoyao.leopard.server.repository.TaskRepository;
|
||||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
@@ -17,36 +13,7 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class TaskService extends SimpleServiceSupport<Task> {
|
public class TaskService extends SimpleServiceSupport<Task> {
|
||||||
private final TransactionTemplate transactionTemplate;
|
public TaskService(TaskRepository repository) {
|
||||||
|
|
||||||
public TaskService(TaskRepository repository, TransactionTemplate transactionTemplate) {
|
|
||||||
super(repository);
|
super(repository);
|
||||||
this.transactionTemplate = transactionTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startTask(String name, String description, Supplier<String> executor) {
|
|
||||||
var task = new Task();
|
|
||||||
task.setName(name);
|
|
||||||
task.setDescription(description);
|
|
||||||
task.setStatus(Task.Status.RUNNING);
|
|
||||||
task.setLaunchedTime(LocalDateTime.now());
|
|
||||||
repository.save(task);
|
|
||||||
transactionTemplate.execute(status -> {
|
|
||||||
try {
|
|
||||||
var result = executor.get();
|
|
||||||
task.setStatus(Task.Status.SUCCESS);
|
|
||||||
if (StrUtil.isNotBlank(result)) {
|
|
||||||
task.setResult(result);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
task.setStatus(Task.Status.FAILURE);
|
|
||||||
task.setError(e.getMessage());
|
|
||||||
status.setRollbackOnly();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
task.setFinishedTime(LocalDateTime.now());
|
|
||||||
repository.save(task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.lanyuanxiaoyao.leopard.server.service;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.repository.TaskTemplateRepository;
|
||||||
|
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TaskTemplateService extends SimpleServiceSupport<TaskTemplate> {
|
||||||
|
public TaskTemplateService(TaskTemplateRepository repository) {
|
||||||
|
super(repository);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.lanyuanxiaoyao.leopard.server.service.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.service.TaskService;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public abstract class TaskRunner {
|
||||||
|
private final TaskService taskService;
|
||||||
|
|
||||||
|
protected TaskRunner(TaskService taskService) {
|
||||||
|
this.taskService = taskService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runTask(TaskTemplate template, Map<String, Object> params) {
|
||||||
|
var task = new Task();
|
||||||
|
task.setName(template.getName());
|
||||||
|
task.setDescription(template.getDescription());
|
||||||
|
task.setStatus(Task.Status.RUNNING);
|
||||||
|
task.setLaunchedTime(LocalDateTime.now());
|
||||||
|
task.setId(taskService.save(task));
|
||||||
|
try {
|
||||||
|
var result = run(params);
|
||||||
|
task.setStatus(Task.Status.SUCCESS);
|
||||||
|
if (StrUtil.isNotBlank(result)) {
|
||||||
|
task.setResult(result);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
task.setStatus(Task.Status.FAILURE);
|
||||||
|
task.setError(e.getMessage());
|
||||||
|
}
|
||||||
|
task.setFinishedTime(LocalDateTime.now());
|
||||||
|
taskService.save(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract String run(Map<String, Object> params);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.lanyuanxiaoyao.leopard.server.service.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.EnumUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.service.StockService;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.service.TaskService;
|
||||||
|
import com.lanyuanxiaoyao.leopard.server.service.TuShareService;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UpdateStockInformationTask extends TaskRunner {
|
||||||
|
private final StockService stockService;
|
||||||
|
private final TuShareService tuShareService;
|
||||||
|
|
||||||
|
public UpdateStockInformationTask(TaskService taskService, StockService stockService, TuShareService tuShareService) {
|
||||||
|
super(taskService);
|
||||||
|
this.stockService = stockService;
|
||||||
|
this.tuShareService = tuShareService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String run(Map<String, Object> params) {
|
||||||
|
var stocks = stockService.list();
|
||||||
|
var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock));
|
||||||
|
tuShareService.stockList()
|
||||||
|
.data()
|
||||||
|
.items()
|
||||||
|
.forEach(item -> {
|
||||||
|
var code = item.get(0);
|
||||||
|
var name = item.get(1);
|
||||||
|
var fullname = item.get(2);
|
||||||
|
var market = EnumUtil.fromString(Stock.Market.class, item.get(3));
|
||||||
|
var industry = item.get(4);
|
||||||
|
var listed = StrUtil.equals("L", item.get(5));
|
||||||
|
if (stocksMap.containsKey(code)) {
|
||||||
|
var stock = stocksMap.get(code);
|
||||||
|
stock.setName(name);
|
||||||
|
stock.setFullname(fullname);
|
||||||
|
stock.setMarket(market);
|
||||||
|
stock.setIndustry(industry);
|
||||||
|
stock.setListed(listed);
|
||||||
|
} else {
|
||||||
|
var stock = new Stock();
|
||||||
|
stock.setCode(code);
|
||||||
|
stock.setName(name);
|
||||||
|
stock.setFullname(fullname);
|
||||||
|
stock.setMarket(market);
|
||||||
|
stock.setIndustry(industry);
|
||||||
|
stock.setListed(listed);
|
||||||
|
stocks.add(stock);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stockService.save(stocks);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,15 @@ import {createRoot} from 'react-dom/client'
|
|||||||
import {createHashRouter, Navigate, type RouteObject, RouterProvider} from 'react-router'
|
import {createHashRouter, Navigate, type RouteObject, RouterProvider} from 'react-router'
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
import './components/amis/Registry.ts'
|
import './components/amis/Registry.ts'
|
||||||
import Overview from "./pages/Overview.tsx";
|
import Overview from './pages/Overview.tsx'
|
||||||
import Root from "./pages/Root.tsx";
|
import Root from './pages/Root.tsx'
|
||||||
import Test from "./pages/Test.tsx";
|
import Test from './pages/Test.tsx'
|
||||||
import StockList from "./pages/stock/StockList.tsx";
|
import StockList from './pages/stock/StockList.tsx'
|
||||||
import StockDetail from './pages/stock/StockDetail.tsx';
|
import StockDetail from './pages/stock/StockDetail.tsx'
|
||||||
import TaskList from "./pages/task/TaskList.tsx";
|
import TaskList from './pages/task/TaskList.tsx'
|
||||||
import TaskAdd from './pages/task/TaskAdd.tsx';
|
import TaskAdd from './pages/task/TaskAdd.tsx'
|
||||||
|
import TaskTemplateList from './pages/task/TaskTemplateList.tsx'
|
||||||
|
import TaskTemplateSave from './pages/task/TaskTemplateSave.tsx'
|
||||||
|
|
||||||
const routes: RouteObject[] = [
|
const routes: RouteObject[] = [
|
||||||
{
|
{
|
||||||
@@ -37,16 +39,12 @@ const routes: RouteObject[] = [
|
|||||||
{
|
{
|
||||||
path: 'detail/:id',
|
path: 'detail/:id',
|
||||||
Component: StockDetail,
|
Component: StockDetail,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'task',
|
path: 'task',
|
||||||
children: [
|
children: [
|
||||||
{
|
|
||||||
index: true,
|
|
||||||
element: <Navigate to="/task/list" replace/>,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'list',
|
path: 'list',
|
||||||
Component: TaskList,
|
Component: TaskList,
|
||||||
@@ -55,12 +53,25 @@ const routes: RouteObject[] = [
|
|||||||
path: 'add',
|
path: 'add',
|
||||||
Component: TaskAdd,
|
Component: TaskAdd,
|
||||||
},
|
},
|
||||||
]
|
{
|
||||||
|
path: 'template',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'list',
|
||||||
|
Component: TaskTemplateList,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'save/:id',
|
||||||
|
Component: TaskTemplateSave,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'test',
|
path: 'test',
|
||||||
Component: Test,
|
Component: Test,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -44,6 +44,16 @@ const menus = {
|
|||||||
path: '/task',
|
path: '/task',
|
||||||
name: '任务',
|
name: '任务',
|
||||||
icon: <UnorderedListOutlined/>,
|
icon: <UnorderedListOutlined/>,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/task/list',
|
||||||
|
name: '任务列表',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/task/template/list',
|
||||||
|
name: '任务模板',
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/test',
|
path: '/test',
|
||||||
|
|||||||
113
leopard-web/src/pages/task/TaskTemplateList.tsx
Normal file
113
leopard-web/src/pages/task/TaskTemplateList.tsx
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {amisRender, commonInfo, crudCommonOptions, paginationTemplate, remoteMappings} from '../../util/amis.tsx'
|
||||||
|
import {useNavigate} from 'react-router'
|
||||||
|
|
||||||
|
function TaskTemplateList() {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
return (
|
||||||
|
<div className="task-template-list">
|
||||||
|
{amisRender(
|
||||||
|
{
|
||||||
|
type: 'page',
|
||||||
|
title: '任务模板',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'crud',
|
||||||
|
api: {
|
||||||
|
method: 'post',
|
||||||
|
url: `${commonInfo.baseUrl}/task_template/list`,
|
||||||
|
data: {
|
||||||
|
page: {
|
||||||
|
index: '${page}',
|
||||||
|
size: '${perPage}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...crudCommonOptions(),
|
||||||
|
...paginationTemplate(
|
||||||
|
15,
|
||||||
|
undefined,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '',
|
||||||
|
icon: 'fa fa-plus',
|
||||||
|
tooltip: '添加模板',
|
||||||
|
tooltipPlacement: 'top',
|
||||||
|
onEvent: {
|
||||||
|
click: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'custom',
|
||||||
|
// @ts-ignore
|
||||||
|
script: (context, action, event) => {
|
||||||
|
navigate('/task/template/save/-1')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: '名称',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
label: '类型',
|
||||||
|
width: 100,
|
||||||
|
...remoteMappings('task_template_type', 'type'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
width: 100,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '详情',
|
||||||
|
level: 'link',
|
||||||
|
onEvent: {
|
||||||
|
click: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'custom',
|
||||||
|
// @ts-ignore
|
||||||
|
script: (context, action, event) => {
|
||||||
|
navigate(`/task/template/save/${context.props.data['id']}`)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'text-danger',
|
||||||
|
type: 'action',
|
||||||
|
label: '删除',
|
||||||
|
level: 'link',
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: `get:${commonInfo.baseUrl}/task_template/remove/\${id}`,
|
||||||
|
confirmText: '确认删除模板[${name}]?',
|
||||||
|
confirmTitle: "删除",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(TaskTemplateList)
|
||||||
96
leopard-web/src/pages/task/TaskTemplateSave.tsx
Normal file
96
leopard-web/src/pages/task/TaskTemplateSave.tsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {amisRender, commonInfo, remoteOptions} from '../../util/amis.tsx'
|
||||||
|
import {useNavigate, useParams} from 'react-router'
|
||||||
|
|
||||||
|
function TaskTemplateSave() {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const {id} = useParams()
|
||||||
|
return (
|
||||||
|
<div className="task-template-save">
|
||||||
|
{amisRender(
|
||||||
|
{
|
||||||
|
type: 'page',
|
||||||
|
title: '任务模板添加',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
debug: commonInfo.debug,
|
||||||
|
type: 'form',
|
||||||
|
api: `post:${commonInfo.baseUrl}/task_template/save`,
|
||||||
|
initApi: `get:${commonInfo.baseUrl}/task_template/detail/${id}`,
|
||||||
|
initFetchOn: `${id} !== -1`,
|
||||||
|
wrapWithPanel: false,
|
||||||
|
mode: 'horizontal',
|
||||||
|
labelAlign: 'left',
|
||||||
|
onEvent: {
|
||||||
|
submitSucc: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'custom',
|
||||||
|
// @ts-ignore
|
||||||
|
script: (context, action, event) => {
|
||||||
|
navigate(-1)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'hidden',
|
||||||
|
name: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'name',
|
||||||
|
label: '名称',
|
||||||
|
require: true,
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'textarea',
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
|
require: true,
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
label: '任务类型',
|
||||||
|
require: true,
|
||||||
|
selectFirst: true,
|
||||||
|
...remoteOptions('select', 'task_template_type'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visibleOn: 'type === \'CLASS\'',
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'clazz',
|
||||||
|
label: '类路径',
|
||||||
|
require: true,
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button-toolbar',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '提交',
|
||||||
|
actionType: 'submit',
|
||||||
|
level: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '重置',
|
||||||
|
actionType: 'reset',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(TaskTemplateSave)
|
||||||
Reference in New Issue
Block a user