1
1
package run .ikaros .server .core .collection ;
2
2
3
+ import static run .ikaros .api .infra .utils .ReactiveBeanUtils .copyProperties ;
4
+
5
+ import java .time .LocalDateTime ;
6
+ import java .time .Year ;
7
+ import java .util .Objects ;
3
8
import lombok .extern .slf4j .Slf4j ;
9
+ import org .springframework .data .domain .PageRequest ;
10
+ import org .springframework .data .domain .Sort ;
11
+ import org .springframework .data .r2dbc .core .R2dbcEntityTemplate ;
12
+ import org .springframework .data .relational .core .query .Criteria ;
13
+ import org .springframework .data .relational .core .query .Query ;
4
14
import org .springframework .stereotype .Service ;
5
15
import org .springframework .util .Assert ;
16
+ import reactor .core .publisher .Flux ;
6
17
import reactor .core .publisher .Mono ;
18
+ import run .ikaros .api .core .collection .EpisodeCollection ;
19
+ import run .ikaros .api .core .collection .SubjectCollection ;
20
+ import run .ikaros .api .core .collection .vo .FindCollectionCondition ;
21
+ import run .ikaros .api .infra .utils .StringUtils ;
22
+ import run .ikaros .api .store .enums .CollectionCategory ;
7
23
import run .ikaros .api .store .enums .CollectionType ;
24
+ import run .ikaros .api .wrap .PagingWrap ;
8
25
import run .ikaros .server .core .user .UserService ;
26
+ import run .ikaros .server .store .entity .EpisodeCollectionEntity ;
9
27
import run .ikaros .server .store .entity .SubjectCollectionEntity ;
28
+ import run .ikaros .server .store .repository .EpisodeCollectionRepository ;
10
29
import run .ikaros .server .store .repository .SubjectCollectionRepository ;
11
30
12
31
@ Slf4j
13
32
@ Service
14
33
public class DefaultCollectionService implements CollectionService {
15
34
private final SubjectCollectionRepository subjectCollectionRepository ;
35
+ private final EpisodeCollectionRepository episodeCollectionRepository ;
16
36
17
37
private final UserService userService ;
38
+ private final R2dbcEntityTemplate template ;
18
39
40
+ /**
41
+ * Construct a {@link CollectionService} instance.
42
+ */
19
43
public DefaultCollectionService (SubjectCollectionRepository subjectCollectionRepository ,
20
- UserService userService ) {
44
+ EpisodeCollectionRepository episodeCollectionRepository ,
45
+ UserService userService , R2dbcEntityTemplate template ) {
21
46
this .subjectCollectionRepository = subjectCollectionRepository ;
47
+ this .episodeCollectionRepository = episodeCollectionRepository ;
22
48
this .userService = userService ;
49
+ this .template = template ;
23
50
}
24
51
25
52
@ Override
@@ -29,4 +56,108 @@ public Mono<CollectionType> findTypeBySubjectId(Long subjectId) {
29
56
.flatMap (uid -> subjectCollectionRepository .findByUserIdAndSubjectId (uid , subjectId ))
30
57
.map (SubjectCollectionEntity ::getType );
31
58
}
59
+
60
+ @ Override
61
+ public Mono <PagingWrap > listCollectionsByCondition (FindCollectionCondition condition ) {
62
+ Assert .notNull (condition , "'condition' must not null." );
63
+ final Integer page = condition .getPage ();
64
+ Assert .isTrue (page > 0 , "'page' must gt 0." );
65
+ final Integer size = condition .getSize ();
66
+ Assert .isTrue (size > 0 , "'size' must gt 0." );
67
+ final PageRequest pageRequest = PageRequest .of (page - 1 , size );
68
+
69
+ Criteria criteria = Criteria .empty ();
70
+
71
+ if (CollectionCategory .SUBJECT == condition .getCategory ()
72
+ && !Objects .isNull (condition .getType ())) {
73
+ criteria = criteria .and ("type" ).is (condition .getType ());
74
+ }
75
+
76
+ // 范围查询更新时间,用于查询指定时间段的收藏纪录
77
+ String time = condition .getTime ();
78
+ if (CollectionCategory .EPISODE == condition .getCategory ()
79
+ && StringUtils .isNotBlank (time )
80
+ ) {
81
+ if (time .indexOf ('-' ) > 0 ) {
82
+ // 日期范围,例如;2000.9-2010.8
83
+ String [] split = time .split ("-" );
84
+ String first = split [0 ];
85
+ String second = split [1 ];
86
+ LocalDateTime startTime ;
87
+ if (first .indexOf ("." ) > 0 ) {
88
+ String [] split1 = first .split ("\\ ." );
89
+ startTime =
90
+ Year .parse (split1 [0 ]).atMonth (Integer .parseInt (split1 [1 ])).atDay (1 )
91
+ .atStartOfDay ();
92
+ } else {
93
+ startTime = Year .parse (first ).atMonth (1 ).atDay (1 ).atStartOfDay ();
94
+ }
95
+ LocalDateTime endTime ;
96
+ if (second .indexOf ("." ) > 0 ) {
97
+ String [] split2 = second .split ("\\ ." );
98
+ endTime =
99
+ Year .parse (split2 [0 ]).atMonth (Integer .parseInt (split2 [1 ])).atDay (1 )
100
+ .atStartOfDay ().plusMonths (1 );
101
+ } else {
102
+ endTime = Year .parse (second ).atDay (1 ).atStartOfDay ().plusMonths (1 );
103
+ }
104
+ criteria = criteria .and (Criteria .where ("update_time" ).between (startTime , endTime ));
105
+ } else {
106
+ // 单个类型,例如:2020.8
107
+ if (time .indexOf ('.' ) > 0 ) {
108
+ String [] split = time .split ("\\ ." );
109
+ LocalDateTime startTime =
110
+ Year .parse (split [0 ]).atMonth (Integer .parseInt (split [1 ])).atDay (1 )
111
+ .atStartOfDay ();
112
+ criteria = criteria .and (
113
+ Criteria .where ("update_time" ).between (startTime , startTime .plusMonths (1 )));
114
+ } else {
115
+ LocalDateTime startTime = Year .parse (time ).atMonth (1 ).atDay (1 ).atStartOfDay ();
116
+ criteria = criteria .and (
117
+ Criteria .where ("update_time" ).between (startTime , startTime .plusYears (1 )));
118
+ }
119
+ }
120
+ }
121
+
122
+ Query query = Query .query (criteria );
123
+
124
+ if (CollectionCategory .EPISODE == condition .getCategory ()
125
+ && condition .getUpdateTimeDesc ()) {
126
+ query = query .sort (Sort .by (Sort .Order .desc ("update_time" ).nullsLast ()));
127
+ }
128
+
129
+ if (CollectionCategory .EPISODE == condition .getCategory ()) {
130
+ query = query
131
+ .sort (Sort .by (
132
+ condition .getUpdateTimeDesc () ? Sort .Order .desc ("update_time" ).nullsLast ()
133
+ : Sort .Order .asc ("update_time" ).nullsLast ()));
134
+ }
135
+
136
+ query = query .with (pageRequest );
137
+
138
+ Mono <Long > countMono ;
139
+ if (CollectionCategory .EPISODE == condition .getCategory ()) {
140
+ Flux <EpisodeCollectionEntity > episodeCollectionEntityFlux =
141
+ template .select (query , EpisodeCollectionEntity .class );
142
+ countMono = template .count (query , EpisodeCollectionEntity .class );
143
+ return episodeCollectionEntityFlux .map (EpisodeCollectionEntity ::getId )
144
+ .flatMap (episodeCollectionRepository ::findById )
145
+ .flatMap (entity -> copyProperties (entity , new EpisodeCollection ()))
146
+ .collectList ()
147
+ .flatMap (episodeCollections -> countMono
148
+ .map (count -> new PagingWrap <>(page , size , count , episodeCollections )));
149
+ } else if (CollectionCategory .SUBJECT == condition .getCategory ()) {
150
+ Flux <SubjectCollectionEntity > subjectCollectionEntityFlux =
151
+ template .select (query , SubjectCollectionEntity .class );
152
+ countMono = template .count (query , SubjectCollectionEntity .class );
153
+ return subjectCollectionEntityFlux .map (SubjectCollectionEntity ::getId )
154
+ .flatMap (subjectCollectionRepository ::findById )
155
+ .flatMap (entity -> copyProperties (entity , new SubjectCollection ()))
156
+ .collectList ()
157
+ .flatMap (subjects -> countMono
158
+ .map (count -> new PagingWrap <>(page , size , count , subjects )));
159
+ } else {
160
+ return Mono .empty ();
161
+ }
162
+ }
32
163
}
0 commit comments