1
1
import * as React from 'react' ;
2
- import { useCallback , useEffect , useMemo , useState } from 'react' ;
3
- import { Form , Steps , Button , Card , Space , Affix , message , Progress , Badge , notification } from 'antd' ;
4
- import { SaveOutlined , ArrowLeftOutlined , ArrowRightOutlined , CheckOutlined , InfoCircleOutlined } from '@ant-design/icons' ;
2
+ import { useCallback , useEffect , useState } from 'react' ;
3
+ import { Form , Button , Card , Space , Affix , message , Progress , Badge , notification , Divider , Typography } from 'antd' ;
4
+ import { SaveOutlined , FileTextOutlined , InfoCircleOutlined } from '@ant-design/icons' ;
5
5
import { ChallengeFormData } from './types' ;
6
6
7
7
// 导入钩子函数
@@ -27,7 +27,7 @@ import ResponsiveContainer from './components/ResponsiveContainer';
27
27
// 导入样式
28
28
import { styles } from './styles' ;
29
29
30
- const { Step } = Steps ;
30
+ const { Title , Text } = Typography ;
31
31
32
32
/**
33
33
* 备份历史模态框组件
@@ -115,8 +115,7 @@ const ChallengeContributePage: React.FC = () => {
115
115
// 表单实例
116
116
const [ form ] = Form . useForm < ChallengeFormData > ( ) ;
117
117
118
- // 步骤状态
119
- const [ currentStep , setCurrentStep ] = useState < number > ( 0 ) ;
118
+ // 状态
120
119
const [ isBackupModalVisible , setIsBackupModalVisible ] = useState < boolean > ( false ) ;
121
120
const [ formCompletion , setFormCompletion ] = useState < number > ( 0 ) ;
122
121
const [ autoSaveVisible , setAutoSaveVisible ] = useState < boolean > ( false ) ;
@@ -285,117 +284,10 @@ const ChallengeContributePage: React.FC = () => {
285
284
} ;
286
285
} , [ isFormDirty ] ) ;
287
286
288
- // 步骤定义
289
- const steps = [
290
- {
291
- title : '基本信息' ,
292
- content : (
293
- < >
294
- < div style = { styles . stepTitle } > 步骤 1:填写基本信息</ div >
295
- < div style = { styles . stepDescription } >
296
- 请填写挑战的基本信息,包括ID、平台类型、名称等必要信息。这些信息将用于在列表页展示和搜索。
297
- </ div >
298
- < BasicInfo form = { form } />
299
- < DifficultySelector form = { form } />
300
- </ >
301
- ) ,
302
- validationFields : [ 'id' , 'platform' , 'name' , 'difficultyLevel' ]
303
- } ,
304
- {
305
- title : '详细描述' ,
306
- content : (
307
- < >
308
- < div style = { styles . stepTitle } > 步骤 2:填写详细描述</ div >
309
- < div style = { styles . stepDescription } >
310
- 请提供挑战的详细描述和目标网站URL(将自动转为Base64编码)。描述应尽可能详细,包括挑战要求和技术背景。
311
- </ div >
312
- < DescriptionFields form = { form } />
313
- < UrlInput form = { form } />
314
- </ >
315
- ) ,
316
- validationFields : [ 'description' , 'base64Url' ]
317
- } ,
318
- {
319
- title : '标签与解决方案' ,
320
- content : (
321
- < >
322
- < div style = { styles . stepTitle } > 步骤 3:添加标签和解决方案</ div >
323
- < div style = { styles . stepDescription } >
324
- 添加相关技术标签和解决方案链接,帮助其他用户快速识别和解决挑战。好的标签和解决方案资源能显著提高挑战的价值。
325
- </ div >
326
- < TagsSelector
327
- form = { form }
328
- onChange = { handleTagsChange }
329
- />
330
- < SolutionsSection
331
- form = { form }
332
- onChange = { handleSolutionsChange }
333
- />
334
- </ >
335
- ) ,
336
- validationFields : [ 'tags' ]
337
- } ,
338
- {
339
- title : 'YAML预览' ,
340
- content : (
341
- < >
342
- < div style = { styles . stepTitle } > 步骤 4:生成和检查YAML</ div >
343
- < div style = { styles . stepDescription } >
344
- 检查自动生成的YAML内容,确保所有信息正确。您可以复制YAML用于提交挑战。如需修改信息,可以返回前面的步骤进行编辑。
345
- </ div >
346
- < YamlPreviewSection
347
- yamlOutput = { yamlOutput }
348
- onGenerateYaml = { generateYaml }
349
- onCopyYaml = { handleCopyYaml }
350
- />
351
- </ >
352
- ) ,
353
- validationFields : [ ]
354
- }
355
- ] ;
356
-
357
- // 处理步骤变更前的验证
358
- const handleStepChange = async ( step : number ) => {
359
- // 如果是向后移动,验证当前步骤的字段
360
- if ( step > currentStep ) {
361
- try {
362
- // 获取当前步骤所需验证的字段
363
- const fieldsToValidate = steps [ currentStep ] . validationFields ;
364
- if ( fieldsToValidate . length > 0 ) {
365
- await form . validateFields ( fieldsToValidate ) ;
366
- }
367
- // 验证通过,可以移动到下一步
368
- setCurrentStep ( step ) ;
369
- // 如果移动到最后一步,自动生成YAML
370
- if ( step === steps . length - 1 ) {
371
- setTimeout ( ( ) => {
372
- generateYaml ( ) ;
373
- } , 300 ) ;
374
- }
375
- } catch ( error ) {
376
- // 验证失败,显示错误消息
377
- message . error ( '请填写所有必填字段后再继续' ) ;
378
- }
379
- } else {
380
- // 向前移动不需要验证
381
- setCurrentStep ( step ) ;
382
- }
383
- } ;
384
-
385
- // 前进到下一步
386
- const goNext = ( ) => {
387
- handleStepChange ( currentStep + 1 ) ;
388
- } ;
389
-
390
- // 返回上一步
391
- const goPrevious = ( ) => {
392
- handleStepChange ( currentStep - 1 ) ;
393
- } ;
394
-
395
287
return (
396
288
< ResponsiveContainer >
397
289
{ /* 进度指示器 */ }
398
- < div style = { { marginBottom : 16 } } >
290
+ < div style = { styles . progressContainer } >
399
291
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : 8 } } >
400
292
< span > 表单完成度: { formCompletion } %</ span >
401
293
< Badge
@@ -424,15 +316,6 @@ const ChallengeContributePage: React.FC = () => {
424
316
onShowBackups = { showBackupHistory }
425
317
/>
426
318
427
- { /* 步骤导航 */ }
428
- < Card style = { { marginBottom : 20 , ...styles . stepCard } } >
429
- < Steps current = { currentStep } onChange = { handleStepChange } responsive = { true } style = { styles . stepsNav } >
430
- { steps . map ( step => (
431
- < Step key = { step . title } title = { step . title } />
432
- ) ) }
433
- </ Steps >
434
- </ Card >
435
-
436
319
{ /* 表单内容 */ }
437
320
< Form
438
321
form = { form }
@@ -446,12 +329,74 @@ const ChallengeContributePage: React.FC = () => {
446
329
< input type = "hidden" />
447
330
</ Form . Item >
448
331
449
- { /* 当前步骤内容 */ }
450
- < Card style = { styles . stepCard } >
451
- { steps [ currentStep ] . content }
452
- </ Card >
332
+ < div style = { styles . formSection } >
333
+ { /* 基本信息部分 */ }
334
+ < Card style = { styles . stepCard } title = { < Title level = { 4 } > 基本信息</ Title > } >
335
+ < div style = { styles . formSectionContent } >
336
+ < Text type = "secondary" style = { { display : 'block' , marginBottom : 16 } } >
337
+ 请填写挑战的基本信息,包括ID、平台类型、名称等必要信息。这些信息将用于在列表页展示和搜索。
338
+ </ Text >
339
+ < BasicInfo form = { form } />
340
+ < DifficultySelector form = { form } />
341
+ </ div >
342
+ </ Card >
343
+ </ div >
344
+
345
+ < Divider style = { styles . divider } />
346
+
347
+ < div style = { styles . formSection } >
348
+ { /* 详细描述部分 */ }
349
+ < Card style = { styles . stepCard } title = { < Title level = { 4 } > 详细描述</ Title > } >
350
+ < div style = { styles . formSectionContent } >
351
+ < Text type = "secondary" style = { { display : 'block' , marginBottom : 16 } } >
352
+ 请提供挑战的详细描述和目标网站URL(将自动转为Base64编码)。描述应尽可能详细,包括挑战要求和技术背景。
353
+ </ Text >
354
+ < DescriptionFields form = { form } />
355
+ < UrlInput form = { form } />
356
+ </ div >
357
+ </ Card >
358
+ </ div >
359
+
360
+ < Divider style = { styles . divider } />
361
+
362
+ < div style = { styles . formSection } >
363
+ { /* 标签与解决方案部分 */ }
364
+ < Card style = { styles . stepCard } title = { < Title level = { 4 } > 标签与解决方案</ Title > } >
365
+ < div style = { styles . formSectionContent } >
366
+ < Text type = "secondary" style = { { display : 'block' , marginBottom : 16 } } >
367
+ 添加相关技术标签和解决方案链接,帮助其他用户快速识别和解决挑战。好的标签和解决方案资源能显著提高挑战的价值。
368
+ </ Text >
369
+ < TagsSelector
370
+ form = { form }
371
+ onChange = { handleTagsChange }
372
+ />
373
+ < SolutionsSection
374
+ form = { form }
375
+ onChange = { handleSolutionsChange }
376
+ />
377
+ </ div >
378
+ </ Card >
379
+ </ div >
380
+
381
+ < Divider style = { styles . divider } />
382
+
383
+ < div style = { styles . formBottom } >
384
+ { /* YAML预览部分 */ }
385
+ < Card style = { styles . stepCard } title = { < Title level = { 4 } > YAML生成预览</ Title > } >
386
+ < div style = { styles . formSectionContent } >
387
+ < Text type = "secondary" style = { { display : 'block' , marginBottom : 16 } } >
388
+ 检查自动生成的YAML内容,确保所有信息正确。您可以复制YAML用于提交挑战。
389
+ </ Text >
390
+ < YamlPreviewSection
391
+ yamlOutput = { yamlOutput }
392
+ onGenerateYaml = { generateYaml }
393
+ onCopyYaml = { handleCopyYaml }
394
+ />
395
+ </ div >
396
+ </ Card >
397
+ </ div >
453
398
454
- { /* 步骤操作按钮 */ }
399
+ { /* 底部固定操作按钮 */ }
455
400
< Affix offsetBottom = { 20 } >
456
401
< Card style = { styles . footerButtons } >
457
402
< Space >
@@ -460,40 +405,17 @@ const ChallengeContributePage: React.FC = () => {
460
405
onClick = { handleManualSave }
461
406
loading = { isSaving }
462
407
>
463
- 保存
408
+ 保存表单
464
409
</ Button >
465
410
</ Space >
466
411
467
- < Space >
468
- { currentStep > 0 && (
469
- < Button
470
- icon = { < ArrowLeftOutlined /> }
471
- onClick = { goPrevious }
472
- >
473
- 上一步
474
- </ Button >
475
- ) }
476
-
477
- { currentStep < steps . length - 1 && (
478
- < Button
479
- type = "primary"
480
- onClick = { goNext }
481
- icon = { < ArrowRightOutlined /> }
482
- >
483
- 下一步
484
- </ Button >
485
- ) }
486
-
487
- { currentStep === steps . length - 1 && (
488
- < Button
489
- type = "primary"
490
- onClick = { generateYaml }
491
- icon = { < CheckOutlined /> }
492
- >
493
- 生成YAML
494
- </ Button >
495
- ) }
496
- </ Space >
412
+ < Button
413
+ type = "primary"
414
+ onClick = { generateYaml }
415
+ icon = { < FileTextOutlined /> }
416
+ >
417
+ 生成YAML
418
+ </ Button >
497
419
</ Card >
498
420
</ Affix >
499
421
</ Form >
0 commit comments