1
1
import { Button , Card , Elevation , H4 , H5 , Icon , Tag } from '@blueprintjs/core'
2
2
import { Tooltip2 } from '@blueprintjs/popover2'
3
3
4
+ import clsx from 'clsx'
4
5
import { handleCopyShortCode , handleDownloadJSON } from 'services/operation'
5
6
6
7
import { ReLink } from 'components/ReLink'
@@ -19,22 +20,21 @@ export const NeoOperationCard = ({ operation }: { operation: Operation }) => {
19
20
const { data : levels } = useLevels ( )
20
21
21
22
return (
22
- < ReLink search = { { op : operation . id } } className = "no-underline" >
23
- < Card
24
- interactive = { true }
25
- elevation = { Elevation . TWO }
26
- className = "flex flex-col gap-2"
27
- >
23
+ < Card
24
+ interactive = { true }
25
+ elevation = { Elevation . TWO }
26
+ className = "relative flex flex-col gap-2"
27
+ >
28
+ < ReLink search = { { op : operation . id } } className = "block no-underline" >
28
29
< div className = "flex" >
29
30
< Tooltip2
30
31
content = { operation . parsedContent . doc . title }
31
32
className = "grow flex-1 whitespace-nowrap overflow-hidden text-ellipsis"
32
33
>
33
- < H4 className = "p-0 m-0 whitespace-nowrap overflow-hidden text-ellipsis" >
34
+ < H4 className = "p-0 m-0 mr-20 whitespace-nowrap overflow-hidden text-ellipsis" >
34
35
{ operation . parsedContent . doc . title }
35
36
</ H4 >
36
37
</ Tooltip2 >
37
- < CardActions operation = { operation } />
38
38
</ div >
39
39
< div className = "flex items-center text-slate-900" >
40
40
< div className = "flex flex-wrap" >
@@ -105,28 +105,30 @@ export const NeoOperationCard = ({ operation }: { operation: Operation }) => {
105
105
</ Tooltip2 >
106
106
</ div >
107
107
</ div >
108
- </ Card >
109
- </ ReLink >
108
+ </ ReLink >
109
+
110
+ < CardActions className = "absolute top-4 right-4" operation = { operation } />
111
+ </ Card >
110
112
)
111
113
}
112
114
113
115
export const OperationCard = ( { operation } : { operation : Operation } ) => {
114
116
const { data : levels } = useLevels ( )
115
117
116
118
return (
117
- < ReLink
118
- search = { { op : operation . id } }
119
- className = "block mb-4 sm:mb-2 last:mb-0 no-underline"
119
+ < Card
120
+ interactive = { true }
121
+ elevation = { Elevation . TWO }
122
+ className = "relative mb-4 sm:mb-2 last:mb-0"
120
123
>
121
- < Card interactive = { true } elevation = { Elevation . TWO } >
124
+ < ReLink search = { { op : operation . id } } className = "block no-underline" >
122
125
< div className = "flex flex-wrap mb-4 sm:mb-2" >
123
126
{ /* title */ }
124
127
< div className = "flex flex-col gap-3" >
125
128
< div className = "flex gap-2" >
126
129
< H4 className = "inline-block pb-1 border-b-2 border-zinc-200 border-solid mb-2" >
127
130
{ operation . parsedContent . doc . title }
128
131
</ H4 >
129
- < CardActions operation = { operation } />
130
132
</ div >
131
133
< H5 className = "flex items-center text-slate-900 -mt-3" >
132
134
< EDifficultyLevel
@@ -141,48 +143,44 @@ export const OperationCard = ({ operation }: { operation: Operation }) => {
141
143
</ H5 >
142
144
</ div >
143
145
144
- < div className = "lg:flex-1 hidden " />
146
+ < div className = "grow basis-full xl:basis-0 " />
145
147
146
148
{ /* meta */ }
147
- < div className = "flex flex-col flex-1 gap-y-1.5 gap-x-4" >
148
- < div className = "flex flex-wrap sm:justify-end items-center gap-x-4 gap-y-1 text-zinc-500" >
149
- < div className = "flex items-center gap-1.5" >
150
- < Icon icon = "star" />
151
- < OperationRating
152
- className = "text-sm"
153
- operation = { operation }
154
- layout = "horizontal"
155
- />
149
+ < div className = "flex flex-wrap items-start gap-x-4 gap-y-1 text-zinc-500" >
150
+ < div className = "flex items-center gap-1.5" >
151
+ < Icon icon = "star" />
152
+ < OperationRating
153
+ className = "text-sm"
154
+ operation = { operation }
155
+ layout = "horizontal"
156
+ />
157
+ </ div >
158
+
159
+ < Tooltip2 placement = "top" content = { `访问量:${ operation . views } ` } >
160
+ < div >
161
+ < Icon icon = "eye-open" className = "mr-1.5" />
162
+ < span > { operation . views } </ span >
156
163
</ div >
164
+ </ Tooltip2 >
157
165
158
- < Tooltip2 placement = "top" content = { `访问量:${ operation . views } ` } >
159
- < div >
160
- < Icon icon = "eye-open" className = "mr-1.5" />
161
- < span > { operation . views } </ span >
162
- </ div >
163
- </ Tooltip2 >
166
+ < div >
167
+ < Icon icon = "time" className = "mr-1.5" />
168
+ < RelativeTime
169
+ Tooltip2Props = { { placement : 'top' } }
170
+ moment = { operation . uploadTime }
171
+ />
172
+ </ div >
164
173
174
+ < Tooltip2 placement = "top" content = { `作者:${ operation . uploader } ` } >
165
175
< div >
166
- < Icon icon = "time" className = "mr-1.5" />
167
- < RelativeTime
168
- Tooltip2Props = { { placement : 'top' } }
169
- moment = { operation . uploadTime }
170
- />
176
+ < Icon icon = "user" className = "mr-1.5" />
177
+ < span > { operation . uploader } </ span >
171
178
</ div >
172
- </ div >
173
- < div className = "text-zinc-500 self-end" >
174
- < Tooltip2 placement = "top" content = { `作者:${ operation . uploader } ` } >
175
- < div >
176
- < Icon icon = "user" className = "mr-1.5" />
177
- < span > { operation . uploader } </ span >
178
- </ div >
179
- </ Tooltip2 >
180
- </ div >
179
+ </ Tooltip2 >
181
180
</ div >
182
181
</ div >
183
182
< div className = "flex md:flex-row flex-col gap-4" >
184
183
< div className = "text-gray-700 leading-normal md:w-1/2" >
185
- { /* <div className="text-sm text-zinc-600 mb-2 font-bold">作业描述</div> */ }
186
184
< Paragraphs
187
185
content = { operation . parsedContent . doc . details }
188
186
limitHeight = { 21 * 13.5 } // 13 lines, 21px per line; the extra 0.5 line is intentional so the `mask` effect is obvious
@@ -195,8 +193,13 @@ export const OperationCard = ({ operation }: { operation: Operation }) => {
195
193
< OperatorTags operation = { operation } />
196
194
</ div >
197
195
</ div >
198
- </ Card >
199
- </ ReLink >
196
+ </ ReLink >
197
+
198
+ < CardActions
199
+ className = "absolute top-4 xl:top-12 right-[18px]"
200
+ operation = { operation }
201
+ />
202
+ </ Card >
200
203
)
201
204
}
202
205
@@ -230,16 +233,15 @@ const OperatorTags = ({ operation }: { operation: Operation }) => {
230
233
)
231
234
}
232
235
233
- const CardActions = ( { operation } : { operation : Operation } ) => {
236
+ const CardActions = ( {
237
+ className,
238
+ operation,
239
+ } : {
240
+ className ?: string
241
+ operation : Operation
242
+ } ) => {
234
243
return (
235
- // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
236
- < div
237
- className = "flex gap-1"
238
- onClick = { ( e ) => {
239
- // 避免点击按钮时触发卡片的链接跳转
240
- e . stopPropagation ( )
241
- } }
242
- >
244
+ < div className = { clsx ( 'flex gap-1' , className ) } >
243
245
< Tooltip2
244
246
placement = "bottom"
245
247
content = {
@@ -249,10 +251,7 @@ const CardActions = ({ operation }: { operation: Operation }) => {
249
251
< Button
250
252
small
251
253
icon = "download"
252
- onClick = { ( e ) => {
253
- e . stopPropagation ( )
254
- handleDownloadJSON ( operation . parsedContent )
255
- } }
254
+ onClick = { ( ) => handleDownloadJSON ( operation . parsedContent ) }
256
255
/>
257
256
</ Tooltip2 >
258
257
< Tooltip2
@@ -264,10 +263,7 @@ const CardActions = ({ operation }: { operation: Operation }) => {
264
263
< Button
265
264
small
266
265
icon = "clipboard"
267
- onClick = { ( e ) => {
268
- e . stopPropagation ( )
269
- handleCopyShortCode ( operation )
270
- } }
266
+ onClick = { ( ) => handleCopyShortCode ( operation ) }
271
267
/>
272
268
</ Tooltip2 >
273
269
< Tooltip2
0 commit comments