Skip to content

Commit cdcf17a

Browse files
committed
前端优化 - 优化 Markdown 展示 + 优化等待进度条效果
1 parent 8d574fd commit cdcf17a

File tree

3 files changed

+333
-41
lines changed

3 files changed

+333
-41
lines changed

coder-test-frontend/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88
"preview": "vite preview"
99
},
1010
"dependencies": {
11-
"vue": "^3.4.0",
12-
"vue-router": "^4.2.5",
11+
"@element-plus/icons-vue": "^2.3.1",
1312
"axios": "^1.6.2",
1413
"element-plus": "^2.4.4",
15-
"@element-plus/icons-vue": "^2.3.1",
16-
"pinia": "^2.1.7"
14+
"markdown-it": "^14.1.0",
15+
"pinia": "^2.1.7",
16+
"vue": "^3.4.0",
17+
"vue-router": "^4.2.5"
1718
},
1819
"devDependencies": {
1920
"@vitejs/plugin-vue": "^4.5.2",

coder-test-frontend/src/views/Challenge.vue

Lines changed: 163 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@
2929
:style="{ left: loadingPosition.x + 'px', top: loadingPosition.y + 'px' }"
3030
/>
3131
<div class="loading-text">正在生成关卡中...</div>
32+
<div class="progress-container">
33+
<el-progress
34+
:percentage="generateProgress"
35+
:stroke-width="6"
36+
:show-text="false"
37+
color="#DAA520"
38+
/>
39+
<div class="progress-text">{{ generateProgress }}%</div>
40+
</div>
3241
</div>
3342
</div>
3443
</el-card>
@@ -135,6 +144,15 @@
135144
:style="{ left: submitLoadingPosition.x + 'px', top: submitLoadingPosition.y + 'px' }"
136145
/>
137146
<div class="loading-text">正在提交答案...</div>
147+
<div class="progress-container">
148+
<el-progress
149+
:percentage="submitProgress"
150+
:stroke-width="6"
151+
:show-text="false"
152+
color="#DAA520"
153+
/>
154+
<div class="progress-text">{{ submitProgress }}%</div>
155+
</div>
138156
</div>
139157
</div>
140158
</div>
@@ -170,17 +188,25 @@ const currentLevel = ref(null)
170188
const selectedOptions = ref([])
171189
const draggedOption = ref(null)
172190
191+
// 进度条相关
192+
const generateProgress = ref(0)
193+
const submitProgress = ref(0)
194+
let generateProgressInterval = null
195+
let submitProgressInterval = null
196+
173197
// 加载图标随机移动相关
174198
const loadingPosition = ref({ x: 0, y: 0 })
175199
const submitLoadingPosition = ref({ x: 0, y: 0 })
176200
let loadingInterval = null
177201
let submitLoadingInterval = null
178202
179203
// 随机移动函数
180-
const getRandomPosition = (containerWidth = 300, containerHeight = 80, iconSize = 40) => {
204+
const getRandomPosition = (containerWidth = 300, containerHeight = 180, iconSize = 40) => {
205+
// 限制图标在容器上半部分活动,避免与文案和进度条重叠
206+
const maxY = Math.min(containerHeight - 120, 35) // 保留底部给文案和进度条
181207
return {
182-
x: Math.random() * (containerWidth - iconSize),
183-
y: Math.random() * (containerHeight - iconSize)
208+
x: Math.random() * (containerWidth - iconSize - 10) + 5, // 左右留5px边距
209+
y: Math.random() * maxY + 5 // 上方留5px边距
184210
}
185211
}
186212
@@ -192,8 +218,8 @@ const startRandomMovement = (positionRef, intervalRef) => {
192218
193219
// 根据屏幕大小调整容器尺寸
194220
const isMobile = window.innerWidth <= 768
195-
const containerWidth = isMobile ? 210 : 260
196-
const containerHeight = isMobile ? 30 : 40
221+
const containerWidth = isMobile ? 250 : 300
222+
const containerHeight = isMobile ? 160 : 180
197223
const iconSize = isMobile ? 35 : 40
198224
199225
// 初始位置
@@ -212,6 +238,41 @@ const stopRandomMovement = (intervalRef) => {
212238
}
213239
}
214240
241+
// 进度条模拟逻辑
242+
const simulateProgress = (progressRef, type = 'generate') => {
243+
progressRef.value = 0
244+
let currentProgress = 0
245+
246+
return setInterval(() => {
247+
if (currentProgress < 30) {
248+
// 前30%:快速增长(模拟初始化)
249+
currentProgress += Math.random() * 8 + 3
250+
} else if (currentProgress < 60) {
251+
// 30%-60%:中等速度(模拟处理中)
252+
currentProgress += Math.random() * 4 + 2
253+
} else if (currentProgress < 85) {
254+
// 60%-85%:较慢速度(模拟深度处理)
255+
currentProgress += Math.random() * 2 + 1
256+
} else if (currentProgress < 99) {
257+
// 85%-99%:很慢速度(模拟最终处理)
258+
currentProgress += Math.random() * 0.5 + 0.2
259+
}
260+
261+
// 确保不超过99%,最后1%由实际完成时设置
262+
progressRef.value = Math.min(Math.floor(currentProgress), 99)
263+
}, type === 'generate' ? 300 : 200) // 生成关卡稍慢,提交答案稍快
264+
}
265+
266+
const stopProgress = (intervalRef) => {
267+
if (intervalRef) {
268+
clearInterval(intervalRef)
269+
}
270+
}
271+
272+
const completeProgress = (progressRef) => {
273+
progressRef.value = 100
274+
}
275+
215276
// 计算可用选项(排除已选择的)
216277
const availableOptions = computed(() => {
217278
if (!currentLevel.value?.options) return []
@@ -259,16 +320,34 @@ const generateLevel = async () => {
259320
console.log('使用的薪资:', userSalary)
260321
261322
generating.value = true
323+
// 启动进度条模拟
324+
generateProgressInterval = simulateProgress(generateProgress, 'generate')
325+
262326
try {
263327
const levelData = await generateLevelAPI({ salary: userSalary })
264328
currentLevel.value = levelData
265329
selectedOptions.value = []
266-
ElMessage.success('关卡生成成功!')
330+
331+
// 完成进度条
332+
completeProgress(generateProgress)
333+
334+
// 短暂延迟后显示成功消息,让用户看到100%
335+
setTimeout(() => {
336+
ElMessage.success('关卡生成成功!')
337+
}, 200)
267338
} catch (error) {
268339
console.error('生成关卡失败:', error)
269340
ElMessage.error('生成关卡失败,请重试')
270341
} finally {
271-
generating.value = false
342+
// 清理进度条定时器
343+
stopProgress(generateProgressInterval)
344+
generateProgressInterval = null
345+
346+
// 延迟重置状态,让用户看到完成效果
347+
setTimeout(() => {
348+
generating.value = false
349+
generateProgress.value = 0
350+
}, 500)
272351
}
273352
}
274353
@@ -336,6 +415,9 @@ const submitAnswer = async () => {
336415
}
337416
338417
submitting.value = true
418+
// 启动进度条模拟
419+
submitProgressInterval = simulateProgress(submitProgress, 'submit')
420+
339421
try {
340422
const submitData = {
341423
levelId: currentLevel.value.id,
@@ -351,15 +433,28 @@ const submitAnswer = async () => {
351433
userStore.updateUserSalary(newSalary)
352434
}
353435
354-
// 跳转到结果页面
355-
console.log('准备跳转到结果页面:', `/result/${result.id}`)
356-
router.push(`/result/${result.id}`)
436+
// 完成进度条
437+
completeProgress(submitProgress)
438+
439+
// 短暂延迟后跳转,让用户看到100%
440+
setTimeout(() => {
441+
console.log('准备跳转到结果页面:', `/result/${result.id}`)
442+
router.push(`/result/${result.id}`)
443+
}, 300)
357444
358445
} catch (error) {
359446
console.error('提交答案失败:', error)
360447
ElMessage.error('提交答案失败,请重试')
361-
} finally {
362-
submitting.value = false
448+
449+
// 清理进度条定时器
450+
stopProgress(submitProgressInterval)
451+
submitProgressInterval = null
452+
453+
// 重置状态
454+
setTimeout(() => {
455+
submitting.value = false
456+
submitProgress.value = 0
457+
}, 300)
363458
}
364459
}
365460
@@ -376,6 +471,11 @@ watch(generating, (newVal) => {
376471
} else {
377472
stopRandomMovement(loadingInterval)
378473
loadingInterval = null
474+
// 确保进度条定时器也被清理
475+
if (generateProgressInterval) {
476+
stopProgress(generateProgressInterval)
477+
generateProgressInterval = null
478+
}
379479
}
380480
})
381481
@@ -386,6 +486,11 @@ watch(submitting, (newVal) => {
386486
} else {
387487
stopRandomMovement(submitLoadingInterval)
388488
submitLoadingInterval = null
489+
// 确保进度条定时器也被清理
490+
if (submitProgressInterval) {
491+
stopProgress(submitProgressInterval)
492+
submitProgressInterval = null
493+
}
389494
}
390495
})
391496
@@ -397,9 +502,11 @@ onMounted(() => {
397502
})
398503
399504
onUnmounted(() => {
400-
// 组件销毁时清理定时器
505+
// 组件销毁时清理所有定时器
401506
stopRandomMovement(loadingInterval)
402507
stopRandomMovement(submitLoadingInterval)
508+
stopProgress(generateProgressInterval)
509+
stopProgress(submitProgressInterval)
403510
})
404511
</script>
405512
@@ -605,7 +712,7 @@ onUnmounted(() => {
605712
.custom-loading-area {
606713
position: relative;
607714
width: 300px;
608-
height: 80px;
715+
height: 180px;
609716
margin: 20px auto;
610717
border: 2px dashed var(--border-medium);
611718
border-radius: 12px;
@@ -619,17 +726,46 @@ onUnmounted(() => {
619726
height: 40px;
620727
transition: all 0.3s ease-in-out;
621728
z-index: 2;
729+
/* 限制图标活动范围,避免与文案和进度条重叠 */
730+
top: 5px;
622731
}
623732
624733
.loading-text {
625734
position: absolute;
626-
bottom: 5px;
735+
bottom: 32px;
627736
left: 50%;
628737
transform: translateX(-50%);
629738
color: var(--text-secondary);
630739
font-size: 14px;
631740
font-weight: 500;
741+
z-index: 3;
742+
background: var(--bg-secondary);
743+
padding: 2px 8px;
744+
border-radius: 4px;
745+
}
746+
747+
/* 进度条容器 */
748+
.progress-container {
749+
position: absolute;
750+
bottom: 8px;
751+
left: 20px;
752+
right: 20px;
632753
z-index: 1;
754+
display: flex;
755+
align-items: center;
756+
gap: 10px;
757+
}
758+
759+
.progress-container .el-progress {
760+
flex: 1;
761+
}
762+
763+
.progress-text {
764+
color: var(--text-secondary);
765+
font-size: 12px;
766+
font-weight: 600;
767+
min-width: 30px;
768+
text-align: right;
633769
}
634770
635771
.submit-loading {
@@ -656,12 +792,23 @@ onUnmounted(() => {
656792
657793
.custom-loading-area {
658794
width: 250px;
659-
height: 70px;
795+
height: 80px;
660796
}
661797
662798
.custom-loading-icon {
663799
width: 35px;
664800
height: 35px;
665801
}
802+
803+
.progress-container {
804+
left: 15px;
805+
right: 15px;
806+
gap: 8px;
807+
}
808+
809+
.progress-text {
810+
font-size: 11px;
811+
min-width: 28px;
812+
}
666813
}
667814
</style>

0 commit comments

Comments
 (0)