1
0

feat(all): 增加简单的任务管理

This commit is contained in:
2025-08-30 22:20:16 +08:00
parent 877f460c26
commit 334840c784
10 changed files with 98 additions and 138 deletions

View File

@@ -75,6 +75,14 @@
<option name="TAB_SIZE" value="2" /> <option name="TAB_SIZE" value="2" />
</indentOptions> </indentOptions>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="XML">
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin"> <codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings> </codeStyleSettings>

72
.idea/compiler.xml generated
View File

@@ -85,78 +85,6 @@
<entry name="$MAVEN_REPOSITORY$/org/easymock/easymock/5.6.0/easymock-5.6.0.jar" /> <entry name="$MAVEN_REPOSITORY$/org/easymock/easymock/5.6.0/easymock-5.6.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/objenesis/objenesis/3.4/objenesis-3.4.jar" /> <entry name="$MAVEN_REPOSITORY$/org/objenesis/objenesis/3.4/objenesis-3.4.jar" />
<entry name="$MAVEN_REPOSITORY$/org/javassist/javassist/3.30.2-GA/javassist-3.30.2-GA.jar" /> <entry name="$MAVEN_REPOSITORY$/org/javassist/javassist/3.30.2-GA/javassist-3.30.2-GA.jar" />
<entry name="$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-configuration-processor/3.5.0/spring-boot-configuration-processor-3.5.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.38/lombok-1.18.38.jar" />
<entry name="$MAVEN_REPOSITORY$/org/hibernate/orm/hibernate-jpamodelgen/6.6.8.Final/hibernate-jpamodelgen-6.6.8.Final.jar" />
<entry name="$MAVEN_REPOSITORY$/org/hibernate/orm/hibernate-core/6.6.8.Final/hibernate-core-6.6.8.Final.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/persistence/jakarta.persistence-api/3.2.0/jakarta.persistence-api-3.2.0.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/transaction/jakarta.transaction-api/2.0.1/jakarta.transaction-api-2.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jboss/logging/jboss-logging/3.5.0.Final/jboss-logging-3.5.0.Final.jar" />
<entry name="$MAVEN_REPOSITORY$/org/hibernate/common/hibernate-commons-annotations/7.0.3.Final/hibernate-commons-annotations-7.0.3.Final.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/jandex/3.2.0/jandex-3.2.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/fasterxml/classmate/1.5.1/classmate-1.5.1.jar" />
<entry name="$MAVEN_REPOSITORY$/net/bytebuddy/byte-buddy/1.15.11/byte-buddy-1.15.11.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/xml/bind/jakarta.xml.bind-api/4.0.0/jakarta.xml.bind-api-4.0.0.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/activation/jakarta.activation-api/2.1.0/jakarta.activation-api-2.1.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/glassfish/jaxb/jaxb-runtime/4.0.2/jaxb-runtime-4.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/glassfish/jaxb/jaxb-core/4.0.2/jaxb-core-4.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/eclipse/angus/angus-activation/2.0.0/angus-activation-2.0.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/glassfish/jaxb/txw2/4.0.2/txw2-4.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/sun/istack/istack-commons-runtime/4.1.1/istack-commons-runtime-4.1.1.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.13.0/antlr4-runtime-4.13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/validation/jakarta.validation-api/3.0.2/jakarta.validation-api-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/annotation/jakarta.annotation-api/2.1.1/jakarta.annotation-api-2.1.1.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/openfeign/querydsl/querydsl-apt/7.0/querydsl-apt-7.0-jpa.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/openfeign/querydsl/querydsl-codegen/7.0/querydsl-codegen-7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/openfeign/querydsl/querydsl-core/7.0/querydsl-core-7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/projectreactor/reactor-core/3.7.6/reactor-core-3.7.6.jar" />
<entry name="$MAVEN_REPOSITORY$/org/reactivestreams/reactive-streams/1.0.4/reactive-streams-1.0.4.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/openfeign/querydsl/querydsl-codegen-utils/7.0/querydsl-codegen-utils-7.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/eclipse/jdt/ecj/3.40.0/ecj-3.40.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/classgraph/classgraph/4.8.179/classgraph-4.8.179.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/26.0.2/annotations-26.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/dev/morphia/morphia/morphia-core/2.5.0/morphia-core-2.5.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/config/smallrye-config/3.10.1/smallrye-config-3.10.1.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/config/smallrye-config-core/3.10.1/smallrye-config-core-3.10.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/eclipse/microprofile/config/microprofile-config-api/3.1/microprofile-config-api-3.1.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/common/smallrye-common-annotation/2.8.0/smallrye-common-annotation-2.8.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/common/smallrye-common-expression/2.8.0/smallrye-common-expression-2.8.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/common/smallrye-common-function/2.8.0/smallrye-common-function-2.8.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/common/smallrye-common-constraint/2.8.0/smallrye-common-constraint-2.8.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/common/smallrye-common-classloader/2.8.0/smallrye-common-classloader-2.8.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/ow2/asm/asm/9.8/asm-9.8.jar" />
<entry name="$MAVEN_REPOSITORY$/io/smallrye/config/smallrye-config-common/3.10.1/smallrye-config-common-3.10.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mongodb/mongodb-driver-sync/5.4.0/mongodb-driver-sync-5.4.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mongodb/bson/5.4.0/bson-5.4.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mongodb/mongodb-driver-core/5.4.0/mongodb-driver-core-5.4.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mongodb/bson-record-codec/5.4.0/bson-record-codec-5.4.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mongodb/mongodb-driver-legacy/5.4.0/mongodb-driver-legacy-5.4.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar" />
<entry name="$MAVEN_REPOSITORY$/com/github/spotbugs/spotbugs-annotations/4.8.6/spotbugs-annotations-4.8.6.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/semver4j/semver4j/5.6.0/semver4j-5.6.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jsoup/jsoup/1.18.3/jsoup-1.18.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/hibernate/orm/hibernate-envers/7.0.0.Beta1/hibernate-envers-7.0.0.Beta1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/hibernate/models/hibernate-models/0.8.6/hibernate-models-0.8.6.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/openfeign/querydsl/querydsl-core/7.0/querydsl-core-7.0-tests.jar" />
<entry name="$MAVEN_REPOSITORY$/org/joda/joda-money/2.0.2/joda-money-2.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter/5.13.1/junit-jupiter-5.13.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.13.1/junit-jupiter-api-5.13.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.13.1/junit-platform-commons-1.13.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-params/5.13.1/junit-jupiter-params-5.13.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-engine/5.13.1/junit-jupiter-engine-5.13.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-engine/1.13.1/junit-platform-engine-1.13.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/assertj/assertj-core/3.27.3/assertj-core-3.27.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/junit/vintage/junit-vintage-engine/5.13.1/junit-vintage-engine-5.13.1.jar" />
<entry name="$MAVEN_REPOSITORY$/junit/junit/4.13.2/junit-4.13.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/easymock/easymock/5.6.0/easymock-5.6.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/objenesis/objenesis/3.4/objenesis-3.4.jar" />
<entry name="$MAVEN_REPOSITORY$/org/javassist/javassist/3.30.2-GA/javassist-3.30.2-GA.jar" />
</processorPath> </processorPath>
<module name="leopard-server" /> <module name="leopard-server" />
</profile> </profile>

View File

@@ -1,7 +1,6 @@
package com.lanyuanxiaoyao.leopard.server; package com.lanyuanxiaoyao.leopard.server;
import com.blinkfox.fenix.EnableFenix; import com.blinkfox.fenix.EnableFenix;
import com.lanyuanxiaoyao.leopard.server.service.StockService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;

View File

@@ -60,7 +60,7 @@ public class Task extends SimpleEntity {
@Column(nullable = false) @Column(nullable = false)
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Comment("任务状态") @Comment("任务状态")
private Status status; private Status status = Status.RUNNING;
@Comment("任务开始时间") @Comment("任务开始时间")
private LocalDateTime launchedTime; private LocalDateTime launchedTime;
@Comment("任务结束时间") @Comment("任务结束时间")
@@ -69,7 +69,6 @@ public class Task extends SimpleEntity {
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum Status implements SimpleEnum { public enum Status implements SimpleEnum {
PENDING("待执行"),
RUNNING("执行中"), RUNNING("执行中"),
SUCCESS("成功"), SUCCESS("成功"),
FAILURE("失败"), FAILURE("失败"),

View File

@@ -9,7 +9,6 @@ import java.util.List;
import java.util.stream.Collectors; 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;
import org.springframework.transaction.annotation.Transactional;
/** /**
* @author lanyuanxiaoyao * @author lanyuanxiaoyao
@@ -20,51 +19,57 @@ import org.springframework.transaction.annotation.Transactional;
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 TuShareService tuShareService;
private final TaskService taskService;
public StockService(StockRepository repository, TuShareService tuShareService) { public StockService(StockRepository repository, TuShareService tuShareService, TaskService taskService) {
super(repository); super(repository);
this.stockRepository = repository; this.stockRepository = repository;
this.tuShareService = tuShareService; this.tuShareService = tuShareService;
this.taskService = taskService;
} }
public List<String> findDistinctIndustries() { public List<String> findDistinctIndustries() {
return stockRepository.findDistinctIndustries(); return stockRepository.findDistinctIndustries();
} }
@Transactional(rollbackFor = Throwable.class)
public void refresh() { public void refresh() {
log.info("开始刷新股票列表"); taskService.startTask(
var stocks = list(); "股票列表刷新",
var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock)); "股票列表刷新",
tuShareService.stockList() () -> {
.data() var stocks = list();
.items() var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock));
.forEach(item -> { tuShareService.stockList()
var code = item.get(0); .data()
var name = item.get(1); .items()
var fullname = item.get(2); .forEach(item -> {
var market = EnumUtil.fromString(Stock.Market.class, item.get(3)); var code = item.get(0);
var industry = item.get(4); var name = item.get(1);
var listed = StrUtil.equals("L", item.get(5)); var fullname = item.get(2);
if (stocksMap.containsKey(code)) { var market = EnumUtil.fromString(Stock.Market.class, item.get(3));
var stock = stocksMap.get(code); var industry = item.get(4);
stock.setName(name); var listed = StrUtil.equals("L", item.get(5));
stock.setFullname(fullname); if (stocksMap.containsKey(code)) {
stock.setMarket(market); var stock = stocksMap.get(code);
stock.setIndustry(industry); stock.setName(name);
stock.setListed(listed); stock.setFullname(fullname);
} else { stock.setMarket(market);
var stock = new Stock(); stock.setIndustry(industry);
stock.setCode(code); stock.setListed(listed);
stock.setName(name); } else {
stock.setFullname(fullname); var stock = new Stock();
stock.setMarket(market); stock.setCode(code);
stock.setIndustry(industry); stock.setName(name);
stock.setListed(listed); stock.setFullname(fullname);
stocks.add(stock); stock.setMarket(market);
} stock.setIndustry(industry);
}); stock.setListed(listed);
repository.saveAll(stocks); stocks.add(stock);
log.info("股票列表刷新完成"); }
});
repository.saveOrUpdateAllByNotNullProperties(stocks);
return null;
}
);
} }
} }

View File

@@ -1,11 +1,14 @@
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.repository.SimpleRepository;
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
@@ -14,9 +17,36 @@ import org.springframework.stereotype.Service;
@Slf4j @Slf4j
@Service @Service
public class TaskService extends SimpleServiceSupport<Task> { public class TaskService extends SimpleServiceSupport<Task> {
private final TransactionTemplate transactionTemplate;
public TaskService(TaskRepository repository, TransactionTemplate transactionTemplate) {
public TaskService(TaskRepository repository) {
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);
} }
} }

View File

@@ -42,7 +42,7 @@ public class TuShareService {
public TuShareResponse stockList() { public TuShareResponse stockList() {
var response = HttpUtil.post(API_URL, buildRequest( var response = HttpUtil.post(API_URL, buildRequest(
"stock_basic", "stock_basic",
Map.of("list_status", "L"), Map.of("list_status", "D,P,L"),
List.of("ts_code", "name", "fullname", "exchange", "industry", "list_status") List.of("ts_code", "name", "fullname", "exchange", "industry", "list_status")
)); ));
var tuShareResponse = mapper.readValue(response, TuShareResponse.class); var tuShareResponse = mapper.readValue(response, TuShareResponse.class);

View File

@@ -1,20 +0,0 @@
package com.lanyuanxiaoyao.leopard.server.task;
import java.util.Map;
/**
* 任务
*
* @author lanyuanxiaoyao
* @version 20250829
*/
public abstract class TaskTemplate {
private String name;
private String description;
public abstract Type getType();
public enum Type {
CLASS
}
}

View File

@@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import {amisRender, commonInfo, crudCommonOptions, paginationTemplate, remoteMappings} from '../../util/amis.tsx' import {amisRender, commonInfo, crudCommonOptions, paginationTemplate, remoteMappings, time} from '../../util/amis.tsx'
import {useNavigate} from 'react-router' import {useNavigate} from 'react-router'
function TaskList() { function TaskList() {
@@ -69,12 +69,16 @@ function TaskList() {
{ {
name: 'launchedTime', name: 'launchedTime',
label: '启动时间', label: '启动时间',
width: 100, width: 150,
align: 'center',
...time('launchedTime'),
}, },
{ {
name: 'finishedTime', name: 'finishedTime',
label: '结束时间', label: '结束时间',
width: 100, width: 150,
align: 'center',
...time('finishedTime'),
}, },
{ {
type: 'operation', type: 'operation',

View File

@@ -25,6 +25,7 @@
<eclipse-collections.version>13.0.0</eclipse-collections.version> <eclipse-collections.version>13.0.0</eclipse-collections.version>
<hutool.version>5.8.39</hutool.version> <hutool.version>5.8.39</hutool.version>
<liteflow.version>2.13.2</liteflow.version>
</properties> </properties>
<dependencies> <dependencies>
@@ -54,6 +55,12 @@
<version>${hutool.version}</version> <version>${hutool.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>${liteflow.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>spring-boot-dependencies</artifactId>