guoyu/fronted_uniapp/pages/exam/detail.vue

1086 lines
35 KiB
Vue
Raw Normal View History

2025-12-03 18:58:36 +08:00
<template>
<view class="exam-detail-container">
<!-- 顶部信息栏 -->
<view class="exam-header">
<view class="header-info">
<text class="exam-name">{{ examInfo.examName || '加载中...' }}</text>
<text class="exam-subject" v-if="examInfo.subjectName">{{ examInfo.subjectName }}</text>
</view>
<view class="timer-section">
<text class="timer-label">剩余时间</text>
<text class="timer-value" :class="{ 'timer-warning': remainingTime < 300 }">
{{ formatTime(remainingTime) }}
</text>
</view>
</view>
<!-- 答题卡 -->
<view class="answer-sheet" v-if="showAnswerSheet">
<view class="sheet-header">
<text class="sheet-title">答题卡</text>
<text class="close-btn" @click="showAnswerSheet = false">×</text>
</view>
<view class="sheet-content">
<view
v-for="(question, index) in questions"
:key="question.id"
class="sheet-item"
:class="{
'answered': answers[question.id] !== undefined && answers[question.id] !== '',
'current': currentIndex === index
}"
@click="jumpToQuestion(index)"
>
{{ index + 1 }}
</view>
</view>
</view>
<!-- 题目区域 -->
<scroll-view
class="questions-container"
scroll-y
:scroll-into-view="'question-' + currentIndex"
scroll-with-animation
>
<view
v-for="(question, index) in questions"
:key="question.id"
:id="'question-' + index"
class="question-item"
>
<view class="question-header">
<text class="question-number"> {{ index + 1 }} </text>
<text class="question-score">{{ question.score }}</text>
</view>
<view class="question-content">
<text class="question-text">
{{ question.questionContent }}
<text v-if="question.questionType === 'multiple'" class="multiple-tip">可多选</text>
</text>
2025-12-03 18:58:36 +08:00
</view>
<!-- 单选题 -->
<view v-if="question.questionType === 'single'" class="options-list">
<view
v-for="(option, optIndex) in parseOptions(question.options)"
:key="optIndex"
class="option-item"
:class="{ 'selected': answers[question.id] === option }"
@click="selectAnswer(question.id, option)"
>
<view class="option-radio">
<view class="radio-dot" v-if="answers[question.id] === option"></view>
</view>
<text class="option-label">{{ getOptionLabel(optIndex) }}</text>
<text class="option-text">{{ option }}</text>
</view>
</view>
<!-- 多选题 -->
<view v-if="question.questionType === 'multiple'">
<view class="multiple-hint">💡 提示本题为多选题可以选择多个答案</view>
<view class="options-list">
<view
v-for="(option, optIndex) in parseOptions(question.options)"
:key="optIndex"
class="option-item"
:class="{ 'selected': isOptionSelected(question.id, option) }"
@click="toggleMultipleAnswer(question.id, option)"
>
2025-12-03 18:58:36 +08:00
<view class="option-checkbox">
<text class="checkbox-icon" v-if="isOptionSelected(question.id, option)"></text>
</view>
<text class="option-label">{{ getOptionLabel(optIndex) }}</text>
<text class="option-text">{{ option }}</text>
</view>
</view>
2025-12-03 18:58:36 +08:00
</view>
<!-- 判断题 -->
<view v-if="question.questionType === 'judge'" class="options-list">
<view
class="option-item"
:class="{ 'selected': answers[question.id] === '正确' }"
@click="selectAnswer(question.id, '正确')"
>
<view class="option-radio">
<view class="radio-dot" v-if="answers[question.id] === '正确'"></view>
</view>
<text class="option-text">正确</text>
</view>
<view
class="option-item"
:class="{ 'selected': answers[question.id] === '错误' }"
@click="selectAnswer(question.id, '错误')"
>
<view class="option-radio">
<view class="radio-dot" v-if="answers[question.id] === '错误'"></view>
</view>
<text class="option-text">错误</text>
</view>
</view>
<!-- 填空题 -->
<view v-if="question.questionType === 'fill'" class="fill-answer">
<textarea
v-model="answers[question.id]"
placeholder="请输入答案"
class="fill-input"
@blur="saveAnswers"
></textarea>
</view>
<!-- 简答题 -->
<view v-if="question.questionType === 'essay'" class="essay-answer">
<textarea
v-model="answers[question.id]"
placeholder="请输入答案"
class="essay-input"
:auto-height="true"
@blur="saveAnswers"
></textarea>
</view>
</view>
</scroll-view>
<!-- 底部操作栏 -->
<view class="bottom-actions">
<button class="btn-sheet" @click="showAnswerSheet = !showAnswerSheet">答题卡</button>
<button
class="btn-prev"
:disabled="currentIndex === 0"
@click="prevQuestion"
>上一题</button>
<button
class="btn-next"
:disabled="currentIndex === questions.length - 1"
@click="nextQuestion"
>下一题</button>
<button class="btn-submit" @click="showSubmitModal = true">提交</button>
</view>
<!-- 提交确认弹窗 -->
<view class="submit-modal" v-if="showSubmitModal" @click.stop>
<view class="modal-mask" @click="showSubmitModal = false"></view>
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">确认提交</text>
</view>
<view class="modal-body">
<text class="modal-text">确定要提交答案吗提交后将无法修改</text>
<view class="answer-stats">
<text class="stats-item">已答题{{ answeredCount }}/{{ questions.length }}</text>
<text class="stats-item">未答题{{ unansweredCount }}</text>
</view>
</view>
<view class="modal-footer">
<button class="btn-cancel" @click="showSubmitModal = false">取消</button>
<button class="btn-confirm" @click="submitExam">确认提交</button>
</view>
</view>
</view>
<!-- 退出确认弹窗 -->
<view class="exit-modal" v-if="showExitModal" @click.stop>
<view class="modal-mask" @click="showExitModal = false"></view>
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">退出考试</text>
</view>
<view class="modal-body">
<view class="answer-stats">
<text class="stats-item">已答题{{ answeredCount }}/{{ questions.length }}</text>
<text class="stats-item">未答题{{ unansweredCount }}</text>
</view>
</view>
<view class="modal-footer">
<button class="btn-cancel" @click="showExitModal = false">取消</button>
<button class="btn-confirm-exit" @click="confirmExit">确定退出</button>
</view>
</view>
</view>
</view>
</template>
<script>
import { getExamQuestions, submitExamAnswer } from '@/api/study/exam.js'
export default {
data() {
return {
examId: null,
examInfo: {},
questions: [],
answers: {},
currentIndex: 0,
loading: false,
showAnswerSheet: false,
showSubmitModal: false,
showExitModal: false,
isExiting: false, // 标记是否正在退出
// 倒计时相关
remainingTime: 0,
timer: null,
startTime: null,
duration: 0
}
},
computed: {
answeredCount() {
// 只计算当前考试题目的答案数量,避免包含旧题目的答案
return this.questions.filter(question => {
const answer = this.answers[question.id]
return answer !== undefined && answer !== '' && answer !== null
}).length
2025-12-03 18:58:36 +08:00
},
unansweredCount() {
return this.questions.length - this.answeredCount
}
},
onLoad(options) {
if (options.id) {
this.examId = options.id
this.loadExamData()
} else {
uni.showToast({
title: '缺少考试ID',
icon: 'none'
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
},
onBackPress() {
// 如果用户已确认退出,不拦截
if (this.isExiting) {
return false
}
// 拦截返回按钮,显示退出确认弹窗
if (this.answeredCount > 0) {
this.showExitModal = true
return true // 阻止默认返回行为
}
return false
},
onUnload() {
this.clearTimer()
// 保存答案到本地(退出时也会保存)
this.saveAnswers()
},
onHide() {
// 页面隐藏时保存答案
this.saveAnswers()
},
methods: {
async loadExamData() {
this.loading = true
try {
const response = await getExamQuestions(this.examId)
if (response.code === 200 && response.data) {
this.examInfo = response.data.exam || {}
this.questions = response.data.questions || []
this.duration = (this.examInfo.duration || 120) * 60 // 转换为秒
// 初始化倒计时
this.remainingTime = this.duration
this.startTime = Date.now()
this.startTimer()
// 加载本地保存的答案
this.loadAnswers()
} else {
throw new Error(response.msg || '加载失败')
}
} catch (error) {
console.error('加载考试数据失败', error)
const errorMsg = error.message || '加载失败'
// 如果是已做过的提示显示模态框而不是toast
if (errorMsg.includes('已经完成过') || errorMsg.includes('不能重复作答')) {
uni.showModal({
title: '提示',
content: errorMsg,
showCancel: false,
confirmText: '我知道了',
success: () => {
uni.navigateBack()
}
})
} else {
uni.showToast({
title: errorMsg,
icon: 'none',
duration: 2000
})
setTimeout(() => {
uni.navigateBack()
}, 2000)
}
} finally {
this.loading = false
}
},
startTimer() {
this.clearTimer()
this.timer = setInterval(() => {
const elapsed = Math.floor((Date.now() - this.startTime) / 1000)
this.remainingTime = Math.max(0, this.duration - elapsed)
if (this.remainingTime <= 0) {
this.clearTimer()
uni.showModal({
title: '时间到',
content: '考试时间已到,系统将自动提交答案。',
showCancel: false,
success: () => {
this.submitExam()
}
})
}
}, 1000)
},
clearTimer() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
formatTime(seconds) {
const hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
const secs = seconds % 60
if (hours > 0) {
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}
return `${minutes}:${secs.toString().padStart(2, '0')}`
},
parseOptions(optionsStr) {
if (!optionsStr) return []
try {
return JSON.parse(optionsStr)
} catch (e) {
// 如果不是JSON尝试按逗号分割
return optionsStr.split(',').map(s => s.trim())
}
},
getOptionLabel(index) {
return String.fromCharCode(65 + index) + '.'
},
selectAnswer(questionId, answer) {
this.$set(this.answers, questionId, answer)
this.saveAnswers()
},
toggleMultipleAnswer(questionId, option) {
const currentAnswer = this.answers[questionId] || ''
const answerArray = currentAnswer ? currentAnswer.split(',') : []
const index = answerArray.indexOf(option)
if (index > -1) {
answerArray.splice(index, 1)
} else {
answerArray.push(option)
}
2025-12-07 01:19:40 +08:00
// 修复:统一使用完整选项文本,并排序确保一致性
const sortedAnswer = answerArray.sort().join(',')
this.$set(this.answers, questionId, sortedAnswer)
2025-12-03 18:58:36 +08:00
this.saveAnswers()
2025-12-07 01:19:40 +08:00
console.log(`多选题答案更新 - 题目${questionId}:`, sortedAnswer)
2025-12-03 18:58:36 +08:00
},
isOptionSelected(questionId, option) {
const answer = this.answers[questionId] || ''
return answer.split(',').includes(option)
},
prevQuestion() {
if (this.currentIndex > 0) {
this.currentIndex--
}
},
nextQuestion() {
if (this.currentIndex < this.questions.length - 1) {
this.currentIndex++
}
},
jumpToQuestion(index) {
this.currentIndex = index
this.showAnswerSheet = false
},
saveAnswers() {
// 保存答案到本地存储包含用户ID以区分不同用户
const userInfo = uni.getStorageSync('userInfo') || {}
const userId = userInfo.userId || userInfo.id
2025-12-03 18:58:36 +08:00
const key = `exam_answers_${this.examId}`
uni.setStorageSync(key, {
userId: userId, // 保存用户ID
2025-12-03 18:58:36 +08:00
answers: this.answers,
timestamp: Date.now()
})
},
loadAnswers() {
// 从本地存储加载答案,但只加载当前用户的答案
const userInfo = uni.getStorageSync('userInfo') || {}
const currentUserId = userInfo.userId || userInfo.id
2025-12-03 18:58:36 +08:00
const key = `exam_answers_${this.examId}`
const saved = uni.getStorageSync(key)
// 验证用户ID只有当前用户的答案才会加载
2025-12-03 18:58:36 +08:00
if (saved && saved.answers) {
if (saved.userId && saved.userId === currentUserId) {
// 用户ID匹配加载答案
this.answers = { ...this.answers, ...saved.answers }
console.log('加载了当前用户的答案缓存')
} else {
// 用户ID不匹配清除旧答案
console.log('检测到用户切换,清除旧答案缓存')
uni.removeStorageSync(key)
this.answers = {}
}
2025-12-03 18:58:36 +08:00
}
},
confirmExit() {
// 保存答案到本地
this.saveAnswers()
// 标记正在退出,防止 onBackPress 拦截
this.isExiting = true
this.showExitModal = false
this.clearTimer()
// 返回上一页
this.$nextTick(() => {
const pages = getCurrentPages()
console.log('当前页面栈:', pages.length)
// 如果页面栈大于1说明有上一页可以返回
if (pages.length > 1) {
uni.navigateBack({
delta: 1
})
} else {
// 如果没有上一页,跳转到考试列表页
uni.redirectTo({
url: '/pages/exam/list'
})
}
})
},
async submitExam() {
this.showSubmitModal = false
this.clearTimer()
// 检查是否有题目
if (!this.questions || this.questions.length === 0) {
uni.showToast({
title: '没有可提交的题目',
icon: 'none'
})
return
}
// 构建答案数组
const answerList = this.questions.map(question => {
if (!question || !question.id) {
console.warn('题目数据不完整:', question)
return null
}
2025-12-07 01:19:40 +08:00
const answer = this.answers[question.id] || ''
console.log(`题目${question.id} [${question.questionType}]:`, {
questionContent: question.questionContent,
userAnswer: answer,
correctAnswer: question.correctAnswer
})
2025-12-03 18:58:36 +08:00
return {
questionId: question.id,
2025-12-07 01:19:40 +08:00
answer: answer
2025-12-03 18:58:36 +08:00
}
}).filter(item => item !== null) // 过滤掉无效项
// 检查答案列表是否为空
if (answerList.length === 0) {
uni.showToast({
title: '答案数据异常,请重试',
icon: 'none'
})
return
}
// 计算用时(秒)
const duration = Math.floor((Date.now() - this.startTime) / 1000)
// 调试信息
console.log('提交答案数据:', {
examId: this.examId,
answerCount: answerList.length,
questionCount: this.questions.length,
duration: duration,
answerList: answerList
})
uni.showLoading({
title: '提交中...',
mask: true
})
try {
const response = await submitExamAnswer(this.examId, answerList, duration)
if (response.code === 200) {
// 清除本地保存的答案
const key = `exam_answers_${this.examId}`
uni.removeStorageSync(key)
uni.hideLoading()
uni.showToast({
title: '提交成功',
icon: 'success'
})
// 跳转到结果页面
setTimeout(() => {
// 检查响应数据中是否有 id
const scoreId = (response.data && response.data.id) ? response.data.id : ''
uni.redirectTo({
url: `/pages/exam/result?examId=${this.examId}${scoreId ? `&scoreId=${scoreId}` : ''}`
})
}, 1500)
} else {
throw new Error(response.msg || '提交失败')
}
} catch (error) {
uni.hideLoading()
console.error('提交答案失败', error)
// 解析错误信息
let errorMessage = '网络错误,请重试'
if (error && error.message) {
errorMessage = error.message
// 如果是后端返回的数组越界错误,给出更友好的提示
if (errorMessage.includes('Index:') && errorMessage.includes('Size:')) {
errorMessage = '提交数据格式错误,请重试'
}
// 如果是已提交的错误,显示特殊提示
if (errorMessage.includes('已提交') || errorMessage.includes('重复提交') || errorMessage.includes('已经完成过')) {
uni.showModal({
title: '提示',
content: errorMessage,
showCancel: false,
confirmText: '返回',
success: () => {
uni.navigateBack()
}
})
return
}
} else if (error && error.errMsg) {
errorMessage = error.errMsg
}
uni.showModal({
title: '提交失败',
content: errorMessage,
showCancel: true,
confirmText: '重试',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
this.submitExam()
} else {
// 重新启动计时器
this.startTimer()
}
}
})
}
}
}
}
</script>
<style lang="scss" scoped>
.exam-detail-container {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #f5f7fa;
}
.exam-header {
background: linear-gradient(135deg, rgb(55 140 224) 0%, rgb(45 120 200) 100%);
padding: 30rpx;
padding-top: calc(var(--status-bar-height) + 30rpx);
display: flex;
justify-content: space-between;
align-items: center;
@media (min-width: 768px) {
padding: 30rpx 40rpx;
padding-top: calc(var(--status-bar-height) + 30rpx);
}
.header-info {
flex: 1;
.exam-name {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #fff;
margin-bottom: 10rpx;
}
.exam-subject {
display: block;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
}
.timer-section {
text-align: right;
.timer-label {
display: block;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 8rpx;
}
.timer-value {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #fff;
&.timer-warning {
color: #ffeb3b;
animation: blink 1s infinite;
}
}
}
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.answer-sheet {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: flex-end;
.sheet-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
background: #fff;
border-bottom: 1rpx solid #f0f0f0;
.sheet-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.close-btn {
font-size: 48rpx;
color: #999;
line-height: 1;
}
}
.sheet-content {
background: #fff;
padding: 30rpx;
max-height: 60vh;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
gap: 20rpx;
.sheet-item {
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border: 2rpx solid #ddd;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
background: #fff;
&.answered {
background: rgb(55 140 224);
color: #fff;
border-color: rgb(55 140 224);
}
&.current {
border-color: rgb(55 140 224);
border-width: 4rpx;
}
}
}
}
.questions-container {
flex: 1;
padding: 20rpx;
overflow-y: auto;
}
.question-item {
background: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
.question-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f0f0f0;
.question-number {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.question-score {
font-size: 24rpx;
color: rgb(55 140 224);
background: #e6f7ff;
padding: 4rpx 12rpx;
border-radius: 8rpx;
}
}
.question-content {
margin-bottom: 30rpx;
.question-text {
font-size: 30rpx;
line-height: 1.6;
color: #333;
.multiple-tip {
color: rgb(55 140 224);
font-size: 26rpx;
font-weight: 500;
margin-left: 8rpx;
}
2025-12-03 18:58:36 +08:00
}
}
.multiple-hint {
padding: 16rpx 20rpx;
margin-bottom: 20rpx;
background: linear-gradient(135deg, #e6f7ff 0%, #f0f9ff 100%);
border-left: 4rpx solid rgb(55 140 224);
border-radius: 8rpx;
font-size: 28rpx;
color: rgb(55 140 224);
line-height: 1.5;
}
2025-12-03 18:58:36 +08:00
}
.options-list {
.option-item {
display: flex;
align-items: center;
padding: 20rpx;
margin-bottom: 16rpx;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
background: #fff;
&.selected {
border-color: rgb(55 140 224);
background: #e6f7ff;
}
.option-radio {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #ddd;
border-radius: 50%;
margin-right: 20rpx;
display: flex;
align-items: center;
justify-content: center;
.radio-dot {
width: 24rpx;
height: 24rpx;
background: rgb(55 140 224);
border-radius: 50%;
}
}
.option-checkbox {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #ddd;
border-radius: 8rpx;
margin-right: 20rpx;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
.checkbox-icon {
color: rgb(55 140 224);
font-size: 28rpx;
font-weight: bold;
}
}
.option-label {
font-size: 28rpx;
color: rgb(55 140 224);
font-weight: bold;
margin-right: 12rpx;
min-width: 60rpx;
}
.option-text {
flex: 1;
font-size: 28rpx;
color: #333;
}
}
}
.fill-answer, .essay-answer {
.fill-input, .essay-input {
width: 100%;
min-height: 120rpx;
padding: 20rpx;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
font-size: 28rpx;
background: #fff;
}
.essay-input {
min-height: 200rpx;
}
}
.bottom-actions {
display: flex;
gap: 10rpx;
padding: 20rpx;
background: #fff;
border-top: 1rpx solid #f0f0f0;
button {
flex: 1;
padding: 20rpx;
border-radius: 8rpx;
font-size: 28rpx;
border: none;
&.btn-sheet {
background: #f5f5f5;
color: #333;
}
&.btn-prev, &.btn-next {
background: #e6f7ff;
color: rgb(55 140 224);
&:disabled {
background: #f5f5f5;
color: #ccc;
}
}
&.btn-submit {
background: linear-gradient(135deg, rgb(55 140 224) 0%, rgb(45 120 200) 100%);
color: #fff;
font-weight: bold;
}
}
}
.submit-modal,
.exit-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
.modal-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(4rpx);
}
.modal-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 600rpx;
max-width: 90%;
background: #fff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
@media (min-width: 768px) {
width: 500px;
border-radius: 20px;
}
.modal-header {
padding: 40rpx 30rpx 30rpx;
text-align: center;
border-bottom: 1rpx solid #f0f0f0;
@media (min-width: 768px) {
padding: 36px 30px 24px;
}
.modal-title {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
@media (min-width: 768px) {
font-size: 32px;
}
}
}
.modal-body {
padding: 40rpx 30rpx;
@media (min-width: 768px) {
padding: 36px 30px;
}
.modal-text {
display: block;
font-size: 30rpx;
color: #333;
margin-bottom: 24rpx;
text-align: center;
line-height: 1.6;
@media (min-width: 768px) {
font-size: 28px;
margin-bottom: 20px;
}
}
.answer-stats {
background: #f8f9fa;
border-radius: 12rpx;
padding: 24rpx;
display: flex;
justify-content: space-around;
@media (min-width: 768px) {
border-radius: 10px;
padding: 20px;
}
.stats-item {
font-size: 28rpx;
color: #666;
line-height: 1.5;
@media (min-width: 768px) {
font-size: 26px;
}
}
}
}
.modal-footer {
display: flex;
border-top: 1rpx solid #f0f0f0;
button {
flex: 1;
padding: 28rpx;
border: none;
font-size: 30rpx;
font-weight: 500;
background: transparent;
transition: background-color 0.2s;
@media (min-width: 768px) {
padding: 24px;
font-size: 28px;
}
&.btn-cancel {
color: #666;
border-right: 1rpx solid #f0f0f0;
&:active {
background: #f5f5f5;
}
}
&.btn-confirm {
color: rgb(55 140 224);
font-weight: 600;
&:active {
background: rgba(55, 140, 224, 0.1);
}
}
&.btn-confirm-exit {
color: #ff4d4f;
font-weight: 600;
&:active {
background: rgba(255, 77, 79, 0.1);
}
}
}
}
}
}
</style>