@@ -32,6 +32,17 @@ const SheetOperator = ({
32
32
existedGroups,
33
33
miniMedia,
34
34
} : SheetOperatorProps ) => {
35
+ // media warning
36
+ useEffect ( ( ) => {
37
+ return ( ) => {
38
+ if ( miniMedia )
39
+ AppToaster . show ( {
40
+ intent : 'warning' ,
41
+ message : '推荐使用大屏幕进行编辑(宽度>600px)!' ,
42
+ } )
43
+ }
44
+ } , [ ] )
45
+
35
46
const operatorScrollRef = useRef < HTMLDivElement > ( null )
36
47
37
48
const defaultProf = useMemo (
@@ -74,36 +85,33 @@ const SheetOperator = ({
74
85
}
75
86
}
76
87
77
- const formattedSubProfessions = useMemo (
78
- ( ) => [ ...defaultSubProf , ...( selectedProf . sub || [ ] ) ] ,
88
+ const [ formattedSubProfessions , operatorsGroupedByProf ] = useMemo (
89
+ ( ) => [
90
+ // handle other operators
91
+ [ ...defaultSubProf , ...( selectedProf . sub || [ ] ) ] ,
92
+ [
93
+ ...OPERATORS ,
94
+ ...existedOperators
95
+ . filter (
96
+ ( item ) => ! OPERATORS . find ( ( opItem ) => opItem . name === item . name ) ,
97
+ )
98
+ . map ( ( { name } ) => {
99
+ return {
100
+ name,
101
+ id : '' ,
102
+ pron : '' ,
103
+ subProf : '' ,
104
+ }
105
+ } ) ,
106
+ ] . filter ( ( item ) => {
107
+ if ( selectedProf . id === defaultSubProf [ 0 ] . id ) return true
108
+ else if ( selectedProf . id === defaultSubProf [ 1 ] . id )
109
+ return item . subProf === 'notchar1' || ! item . pron || ! item . subProf
110
+ else return ! ! selectedProf . sub ?. find ( ( op ) => op . id === item . subProf )
111
+ } ) ,
112
+ ] ,
79
113
[ selectedProf ] ,
80
114
)
81
- const operatorsGroupedByProf = useMemo ( ( ) => {
82
- // 处理自命名干员
83
- const allOperators = [
84
- ...OPERATORS ,
85
- ...existedOperators
86
- . filter (
87
- ( item ) => ! OPERATORS . find ( ( opItem ) => opItem . name === item . name ) ,
88
- )
89
- . map ( ( { name } ) => {
90
- return {
91
- name,
92
- id : '' ,
93
- pron : '' ,
94
- subProf : '' ,
95
- }
96
- } ) ,
97
- ]
98
- if ( selectedProf . id === 'all' ) return allOperators
99
- if ( selectedProf . id === 'others' )
100
- return allOperators . filter (
101
- ( item ) => item . subProf === 'notchar1' || ! item . pron || ! item . subProf ,
102
- )
103
- return allOperators . filter (
104
- ( op ) => ! ! selectedProf . sub ?. find ( ( item ) => item . id === op . subProf ) ,
105
- )
106
- } , [ selectedProf ] )
107
115
108
116
const operatorsGroupedBySubProf = useMemo ( ( ) => {
109
117
if ( selectedSubProf . id === 'all' ) return operatorsGroupedByProf
@@ -117,11 +125,6 @@ const SheetOperator = ({
117
125
)
118
126
} , [ selectedSubProf , selectedProf ] )
119
127
120
- const selectedAllState = useMemo (
121
- ( ) => ! defaultSubProf . find ( ( { id } ) => id === selectedSubProf . id ) ,
122
- [ selectedSubProf ] ,
123
- )
124
-
125
128
const eventHandleProxy = (
126
129
type : EventType ,
127
130
value : Operator ,
@@ -148,27 +151,6 @@ const SheetOperator = ({
148
151
}
149
152
}
150
153
}
151
- const selectAll = ( ) => {
152
- operatorsGroupedBySubProf . forEach ( ( item ) => {
153
- submitOperator ( item , ( ) => { } )
154
- } )
155
- }
156
-
157
- const SelectAll = useMemo (
158
- ( ) => (
159
- < >
160
- { selectedAllState && (
161
- < H6
162
- className = "absolute bottom-full right-0 p-3 cursor-pointer m-0"
163
- onClick = { selectAll }
164
- >
165
- 全选
166
- </ H6 >
167
- ) }
168
- </ >
169
- ) ,
170
- [ selectedAllState , selectAll ] ,
171
- )
172
154
173
155
// pagination about
174
156
const [ pageIndex , setPageIndex ] = useState ( 0 )
@@ -190,25 +172,77 @@ const SheetOperator = ({
190
172
useEffect ( resetPaginationState , [ selectedProf , selectedSubProf ] )
191
173
192
174
const BackToTop = useMemo (
193
- ( ) =>
194
- backToTop && (
175
+ ( ) => (
176
+ < Button
177
+ minimal
178
+ icon = "symbol-triangle-up"
179
+ disabled = { ! backToTop }
180
+ title = { backToTop ? '回到顶部' : undefined }
181
+ onClick = { resetPaginationState }
182
+ />
183
+ ) ,
184
+ [ backToTop ] ,
185
+ )
186
+
187
+ const selectAll = ( ) => {
188
+ operatorsGroupedBySubProf . forEach ( ( item ) => {
189
+ submitOperator ( item , ( ) => { } )
190
+ } )
191
+ }
192
+
193
+ const cancelAll = ( ) => {
194
+ const deleteIndexList : number [ ] = [ ]
195
+ operatorsGroupedBySubProf . forEach ( ( { name } ) => {
196
+ const index = existedOperators . findIndex ( ( item ) => item . name === name )
197
+ if ( index !== - 1 ) deleteIndexList . push ( index )
198
+ } )
199
+ removeOperator ( deleteIndexList )
200
+ }
201
+
202
+ const SelectButtons = useMemo ( ( ) => {
203
+ const [ selectAllState , cancelAllState ] = [
204
+ ! operatorsGroupedBySubProf . every ( ( { name } ) =>
205
+ checkOperatorSelected ( name ) ,
206
+ ) ,
207
+ operatorsGroupedBySubProf . some ( ( { name } ) => checkOperatorSelected ( name ) ) ,
208
+ ]
209
+ return (
210
+ < >
195
211
< Button
196
- className = "absolute right-3 bottom-3"
197
212
minimal
198
- icon = "symbol-triangle-up"
199
- title = "回到顶部"
200
- onClick = { resetPaginationState }
213
+ icon = "circle"
214
+ disabled = { ! cancelAllState }
215
+ title = { `取消选择全部${ existedOperators . length } 位干员` }
216
+ onClick = { cancelAll }
201
217
/>
202
- ) ,
203
- [ backToTop ] ,
218
+ < Button
219
+ minimal
220
+ icon = "selection"
221
+ title = {
222
+ selectAllState
223
+ ? `全选${ operatorsGroupedBySubProf . length } 位干员`
224
+ : undefined
225
+ }
226
+ disabled = { ! selectAllState }
227
+ onClick = { selectAll }
228
+ />
229
+ </ >
230
+ )
231
+ } , [ operatorsGroupedBySubProf , existedOperators ] )
232
+
233
+ const ActionList = (
234
+ < div className = "absolute bottom-0" >
235
+ { SelectButtons }
236
+ { BackToTop }
237
+ </ div >
204
238
)
205
239
206
240
const ShowMoreButton = useMemo (
207
241
( ) => (
208
242
< div className = "flex items-center justify-center pt-3 cursor-default" >
209
243
{ noMore ? (
210
244
< >
211
- < H6 > 已经展示全部干员了</ H6 >
245
+ < H6 > 已经展示全部干员了( { operatorsGroupedBySubProf . length } ) </ H6 >
212
246
{ canEclipse && (
213
247
< H6
214
248
className = "ml-1 cursor-pointer text-sm text-gray-500 hover:text-inherit hover:underline"
@@ -228,61 +262,87 @@ const SheetOperator = ({
228
262
) }
229
263
</ div >
230
264
) ,
231
- [ noMore , canEclipse , pageIndex ] ,
265
+ [ noMore , canEclipse , pageIndex , operatorsGroupedBySubProf . length ] ,
232
266
)
233
267
234
- const ProfSelect = useMemo (
235
- ( ) => (
236
- < div className = "flex flex-row-reverse h-screen sticky top-0 relative" >
237
- < div className = "h-full flex flex-col mr-0.5 w-12" >
238
- { formattedProfessions . map ( ( prof ) => (
239
- < div
240
- key = { prof . id }
241
- className = "grow cursor-pointer relative flex justify-center items-center"
242
- title = { prof . name }
243
- onClick = { ( ) => setSelectedProf ( prof ) }
244
- role = "presentation"
245
- >
246
- { defaultProf . find ( ( { id } ) => id === prof . id ) ? (
247
- < H5 > { prof . name } </ H5 >
248
- ) : (
249
- < img
250
- className = "invert dark:invert-0"
251
- src = { '/assets/prof-icons/' + prof . id + '.png' }
252
- alt = { prof . name }
253
- title = { prof . name }
254
- />
255
- ) }
256
- { prof . id === selectedProf . id && (
257
- < div className = "h-full w-1 bg-black dark:bg-white absolute top-0 right-full rounded" />
258
- ) }
259
- </ div >
260
- ) ) }
261
- </ div >
262
- < Divider />
263
- < div className = "mr-1 h-full flex flex-col justify-center items-end" >
264
- { formattedSubProfessions ?. map ( ( subProf ) => (
265
- < H4
266
- key = { subProf . id }
267
- className = { clsx (
268
- 'truncate cursor-pointer my-3 opacity-50 hover:underline hover:text-black hover:opacity-75' ,
269
- subProf . id === selectedSubProf . id && 'opacity-100 underline' ,
270
- ) }
271
- onClick = { ( ) => setSelectedSubProf ( subProf ) }
272
- >
273
- { subProf . name }
274
- </ H4 >
275
- ) ) }
276
- </ div >
277
- { BackToTop }
268
+ const ProfSelectProf = useMemo ( ( ) => {
269
+ const ClassesManager = {
270
+ profButton : miniMedia ? 'w-6' : 'w-12' ,
271
+ specialProfButton : miniMedia ? '!text-xs truncate' : '' ,
272
+ }
273
+ return (
274
+ < div
275
+ className = { clsx (
276
+ 'h-full flex flex-col mr-0.5' ,
277
+ ClassesManager . profButton ,
278
+ ) }
279
+ >
280
+ { formattedProfessions . map ( ( prof ) => (
281
+ < div
282
+ key = { prof . id }
283
+ className = "grow cursor-pointer relative flex justify-center items-center"
284
+ title = { prof . name }
285
+ onClick = { ( ) => {
286
+ setSelectedProf ( prof )
287
+ setSelectedSubProf ( defaultSubProf [ 0 ] )
288
+ } }
289
+ role = "presentation"
290
+ >
291
+ { defaultProf . find ( ( { id } ) => id === prof . id ) ? (
292
+ < H5 className = { ClassesManager . specialProfButton } > { prof . name } </ H5 >
293
+ ) : (
294
+ < img
295
+ className = "invert dark:invert-0"
296
+ src = { '/assets/prof-icons/' + prof . id + '.png' }
297
+ alt = { prof . name }
298
+ title = { prof . name }
299
+ />
300
+ ) }
301
+ { prof . id === selectedProf . id && (
302
+ < div className = "h-full w-1 bg-black dark:bg-white absolute top-0 right-full rounded" />
303
+ ) }
304
+ </ div >
305
+ ) ) }
278
306
</ div >
279
- ) ,
280
- [ selectedSubProf , selectedProf , backToTop ] ,
307
+ )
308
+ } , [ selectedProf ] )
309
+
310
+ const ProfSelectSubProf = useMemo (
311
+ ( ) =>
312
+ formattedSubProfessions ?. map ( ( subProf ) => (
313
+ < H4
314
+ key = { subProf . id }
315
+ className = { clsx (
316
+ 'truncate cursor-pointer my-3 opacity-50 hover:underline hover:text-black hover:opacity-75' ,
317
+ subProf . id === selectedSubProf . id && 'opacity-100 underline' ,
318
+ ) }
319
+ onClick = { ( ) => setSelectedSubProf ( subProf ) }
320
+ >
321
+ { subProf . name }
322
+ </ H4 >
323
+ ) ) ,
324
+ [ selectedProf , selectedSubProf ] ,
325
+ )
326
+
327
+ const ProfSelect = (
328
+ < div className = "flex flex-row-reverse h-screen sticky top-0 relative" >
329
+ { ProfSelectProf }
330
+ < Divider className = "mr-0" />
331
+ < div
332
+ className = { clsx (
333
+ 'mr-1 h-full flex flex-col justify-center items-end' ,
334
+ miniMedia ? 'absolute right-full' : 'relative' ,
335
+ ) }
336
+ >
337
+ { ProfSelectSubProf }
338
+ { ActionList }
339
+ </ div >
340
+ </ div >
281
341
)
282
342
283
343
return (
284
344
< div className = "flex h-full" >
285
- < div className = "flex-auto px-2 " ref = { operatorScrollRef } >
345
+ < div className = "flex-auto px-1 " ref = { operatorScrollRef } >
286
346
{ operatorsGroupedBySubProf . length ? (
287
347
< >
288
348
< div
@@ -316,7 +376,6 @@ const SheetOperator = ({
316
376
OperatorNoData
317
377
) }
318
378
</ div >
319
- { /* <Divider /> */ }
320
379
{ ProfSelect }
321
380
</ div >
322
381
)
0 commit comments