1
0

feat: 股票集中显示股票对应的得分

This commit is contained in:
2025-10-10 18:04:47 +08:00
parent d3f337e2c4
commit 846c6fe819
7 changed files with 117 additions and 39 deletions

View File

@@ -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<Stock> stocks;
private Set<StockScore> scores;
}

View File

@@ -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;
}

View File

@@ -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<String, Object> params, StepUpdater updater) throws Exception {
public String process(Map<String, Object> 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 """

View File

@@ -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<StockCollection, StockCollectionController.SaveItem, StockCollectionController.ListItem, StockCollectionController.DetailItem> {
public class StockCollectionController extends SimpleControllerSupport<StockCollection, Void, StockCollectionController.ListItem, StockCollectionController.DetailItem> {
private final StockService stockService;
public StockCollectionController(StockCollectionService service, StockService stockService) {
@@ -23,16 +23,13 @@ public class StockCollectionController extends SimpleControllerSupport<StockColl
}
@Override
protected Function<SaveItem, StockCollection> 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<Long> save(Void unused) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected Function<Void, StockCollection> saveItemMapper() {
throw new UnsupportedOperationException();
}
@Override
@@ -41,7 +38,7 @@ public class StockCollectionController extends SimpleControllerSupport<StockColl
collection.getId(),
collection.getName(),
collection.getDescription(),
collection.getStocks().size()
collection.getScores().size()
);
}
@@ -51,22 +48,15 @@ public class StockCollectionController extends SimpleControllerSupport<StockColl
collection.getId(),
collection.getName(),
collection.getDescription(),
collection.getStocks().size(),
collection.getStocks()
collection.getScores().size(),
collection.getScores()
.stream()
.map(StockDetailVo::of)
.collect(Collectors.toSet())
.map(StockScoreVo::of)
.sorted(Comparator.comparing(StockScoreVo::score).reversed())
.toList()
);
}
public record SaveItem(
Long id,
String name,
String description,
Set<Long> stockIds
) {
}
public record ListItem(
Long id,
String name,
@@ -80,7 +70,7 @@ public class StockCollectionController extends SimpleControllerSupport<StockColl
String name,
String description,
Integer count,
Set<StockDetailVo> stocks
List<StockScoreVo> scores
) {
}
}

View File

@@ -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()
);
}
}

View File

@@ -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',
}
]
),
}
]
}

View File

@@ -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<ColumnSchema> = []) {
return [
{
name: 'code',
@@ -370,6 +371,7 @@ export function stockListColumns(navigate: NavigateFunction) {
align: 'center',
...date('listedDate'),
},
...extraColumns,
{
type: 'operation',
label: '操作',