From 846c6fe8194e64d17f6f4bb51d306dbb414bae1b Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Fri, 10 Oct 2025 18:04:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=82=A1=E7=A5=A8=E9=9B=86=E4=B8=AD?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E8=82=A1=E7=A5=A8=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E5=BE=97=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leopard/core/entity/StockCollection.java | 7 +-- .../leopard/core/entity/StockScore.java | 32 +++++++++++++ .../leopard/core/task/PyramidSelect.java | 16 +++++-- .../controller/StockCollectionController.java | 48 ++++++++----------- .../leopard/server/entity/StockScoreVo.java | 33 +++++++++++++ .../src/pages/stock/StockCollectionDetail.tsx | 16 +++++-- leopard-web/src/util/amis.tsx | 4 +- 7 files changed, 117 insertions(+), 39 deletions(-) create mode 100644 leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockScore.java create mode 100644 leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/entity/StockScoreVo.java diff --git a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java index 531c8ac..19340ae 100644 --- a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java +++ b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java @@ -2,10 +2,11 @@ package com.lanyuanxiaoyao.leopard.core.entity; import com.lanyuanxiaoyao.leopard.core.Constants; import com.lanyuanxiaoyao.service.template.entity.SimpleEntity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EntityListeners; -import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import java.util.Set; import lombok.Getter; @@ -31,7 +32,7 @@ public class StockCollection extends SimpleEntity { @Column(nullable = false) private String description; - @ManyToMany + @OneToMany(cascade = CascadeType.ALL) @ToString.Exclude - private Set stocks; + private Set scores; } diff --git a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockScore.java b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockScore.java new file mode 100644 index 0000000..540a47a --- /dev/null +++ b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockScore.java @@ -0,0 +1,32 @@ +package com.lanyuanxiaoyao.leopard.core.entity; + +import com.lanyuanxiaoyao.leopard.core.Constants; +import com.lanyuanxiaoyao.service.template.entity.SimpleEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.ManyToOne; +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.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Setter +@Getter +@ToString(callSuper = true) +@FieldNameConstants +@Entity +@DynamicUpdate +@DynamicInsert +@EntityListeners(AuditingEntityListener.class) +@Table(name = Constants.DATABASE_PREFIX + "stock_score") +public class StockScore extends SimpleEntity { + @ManyToOne + private Stock stock; + @ManyToOne + private StockCollection collection; + private Double score; +} diff --git a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/task/PyramidSelect.java b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/task/PyramidSelect.java index 8c8dcdc..08502f3 100644 --- a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/task/PyramidSelect.java +++ b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/task/PyramidSelect.java @@ -1,9 +1,9 @@ package com.lanyuanxiaoyao.leopard.core.task; import com.lanyuanxiaoyao.leopard.core.entity.StockCollection; +import com.lanyuanxiaoyao.leopard.core.entity.StockScore; import com.lanyuanxiaoyao.leopard.core.repository.StockCollectionRepository; import com.lanyuanxiaoyao.leopard.core.service.selector.PyramidStockSelector; -import com.lanyuanxiaoyao.leopard.core.service.selector.StockSelector; import java.time.LocalDate; import java.util.Map; import java.util.stream.Collectors; @@ -33,13 +33,23 @@ public class PyramidSelect extends TaskRunner { @Transactional(rollbackFor = Throwable.class) @Override - public String process(Map params, StepUpdater updater) throws Exception { + public String process(Map params, StepUpdater updater) { var candidates = pyramidStockSelector.select(new PyramidStockSelector.Request(LocalDate.now().getYear(), 50)); var collection = new StockCollection(); collection.setName("金字塔选股"); collection.setDescription("金字塔选股"); - collection.setStocks(candidates.stream().map(StockSelector.Candidate::stock).collect(Collectors.toSet())); + collection.setScores( + candidates.stream() + .map(candidate -> { + var score = new StockScore(); + score.setStock(candidate.stock()); + score.setScore(candidate.score()); + score.setCollection(collection); + return score; + }) + .collect(Collectors.toSet()) + ); stockCollectionRepository.save(collection); return """ diff --git a/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/controller/StockCollectionController.java b/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/controller/StockCollectionController.java index bebd89e..72c29d3 100644 --- a/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/controller/StockCollectionController.java +++ b/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/controller/StockCollectionController.java @@ -3,18 +3,18 @@ package com.lanyuanxiaoyao.leopard.server.controller; import com.lanyuanxiaoyao.leopard.core.entity.StockCollection; import com.lanyuanxiaoyao.leopard.core.service.StockCollectionService; import com.lanyuanxiaoyao.leopard.core.service.StockService; -import com.lanyuanxiaoyao.leopard.server.entity.StockDetailVo; +import com.lanyuanxiaoyao.leopard.server.entity.StockScoreVo; +import com.lanyuanxiaoyao.service.template.controller.GlobalResponse; import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport; -import java.util.HashSet; -import java.util.Set; +import java.util.Comparator; +import java.util.List; import java.util.function.Function; -import java.util.stream.Collectors; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("stock_collection") -public class StockCollectionController extends SimpleControllerSupport { +public class StockCollectionController extends SimpleControllerSupport { private final StockService stockService; public StockCollectionController(StockCollectionService service, StockService stockService) { @@ -23,16 +23,13 @@ public class StockCollectionController extends SimpleControllerSupport saveItemMapper() { - return item -> { - var collection = new StockCollection(); - collection.setId(item.id()); - collection.setName(item.name()); - collection.setDescription(item.description()); - var stocks = stockService.list(item.stockIds()); - collection.setStocks(new HashSet<>(stocks)); - return collection; - }; + public GlobalResponse save(Void unused) throws Exception { + throw new UnsupportedOperationException(); + } + + @Override + protected Function saveItemMapper() { + throw new UnsupportedOperationException(); } @Override @@ -41,7 +38,7 @@ public class StockCollectionController extends SimpleControllerSupport stockIds - ) { - } - public record ListItem( Long id, String name, @@ -80,7 +70,7 @@ public class StockCollectionController extends SimpleControllerSupport stocks + List scores ) { } } diff --git a/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/entity/StockScoreVo.java b/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/entity/StockScoreVo.java new file mode 100644 index 0000000..d6efd8d --- /dev/null +++ b/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/entity/StockScoreVo.java @@ -0,0 +1,33 @@ +package com.lanyuanxiaoyao.leopard.server.entity; + +import com.lanyuanxiaoyao.leopard.core.entity.Stock; +import com.lanyuanxiaoyao.leopard.core.entity.StockScore; +import java.time.LocalDate; + +/** + * @author lanyuanxiaoyao + * @version 20250917 + */ +public record StockScoreVo( + Long id, + String code, + String name, + String fullname, + Stock.Market market, + String industry, + LocalDate listedDate, + Double score +) { + public static StockScoreVo of(StockScore score) { + return new StockScoreVo( + score.getStock().getId(), + score.getStock().getCode(), + score.getStock().getName(), + score.getStock().getFullname(), + score.getStock().getMarket(), + score.getStock().getIndustry(), + score.getStock().getListedDate(), + score.getScore() + ); + } +} diff --git a/leopard-web/src/pages/stock/StockCollectionDetail.tsx b/leopard-web/src/pages/stock/StockCollectionDetail.tsx index 4032eb1..0143d1e 100644 --- a/leopard-web/src/pages/stock/StockCollectionDetail.tsx +++ b/leopard-web/src/pages/stock/StockCollectionDetail.tsx @@ -15,10 +15,20 @@ function StockCollectionDetail() { body: [ { type: 'crud', - source: '${stocks}', + source: '${scores}', ...crudCommonOptions(), - ...paginationTemplate(15, undefined, ['filter-toggler']), - columns: stockListColumns(navigate), + ...paginationTemplate(100, undefined, ['filter-toggler']), + columns: stockListColumns( + navigate, + [ + { + name: 'score', + label: '得分', + width: 50, + align: 'center', + } + ] + ), } ] } diff --git a/leopard-web/src/util/amis.tsx b/leopard-web/src/util/amis.tsx index c3ad331..7306e62 100644 --- a/leopard-web/src/util/amis.tsx +++ b/leopard-web/src/util/amis.tsx @@ -6,6 +6,7 @@ import '@fortawesome/fontawesome-free/css/all.min.css' import axios from 'axios' import {isEqual} from 'es-toolkit' import type {NavigateFunction} from 'react-router' +import type {ColumnSchema} from 'amis/lib/renderers/Table2' export const commonInfo = { debug: isEqual(import.meta.env.MODE, 'development'), @@ -336,7 +337,7 @@ export function remoteMappings(name: string, field: string) { } } -export function stockListColumns(navigate: NavigateFunction) { +export function stockListColumns(navigate: NavigateFunction, extraColumns: Array = []) { return [ { name: 'code', @@ -370,6 +371,7 @@ export function stockListColumns(navigate: NavigateFunction) { align: 'center', ...date('listedDate'), }, + ...extraColumns, { type: 'operation', label: '操作',