799 lines
20 KiB
Vue
799 lines
20 KiB
Vue
<template>
|
|
<view class="main_div max_page no-touch">
|
|
<nav-bar :is_seat="true"></nav-bar>
|
|
<view class="nav-div">
|
|
<view class="title ellipsis-text">
|
|
{{ paperData.name }}
|
|
</view>
|
|
<view class="back_div" @click="exit_practice">
|
|
<image :src="practiceExitIcon()" class="img"></image>
|
|
<view class="text">退出</view>
|
|
</view>
|
|
</view>
|
|
<view class="countdown-and-question-number-div">
|
|
<view class="top">
|
|
<view class="countdown">
|
|
<text class="grey mr-10">当前题目/总题数</text>
|
|
<text class="bold">{{ questionNumber + 1 }}</text>
|
|
<text class="grey">/{{ storageTopicList.length }}</text>
|
|
</view>
|
|
<view class="question">
|
|
<view class="grey">练习时长</view>
|
|
<view class="countdown_time">
|
|
{{ formatSeconds(practiceTime) }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="progress">
|
|
<uv-line-progress
|
|
:percentage="progress"
|
|
:showText="false"
|
|
activeColor="#FFFFFF"
|
|
inactiveColor="#89B8FF"
|
|
:height="8"
|
|
></uv-line-progress>
|
|
</view>
|
|
</view>
|
|
<view class="scroll_div">
|
|
<swiper
|
|
:disable-touch="showSwiper"
|
|
ref="swiperRef"
|
|
class="swiper"
|
|
:indicator-dots="false"
|
|
@change="swiperChange"
|
|
:current="questionNumber"
|
|
easing-function="linear"
|
|
@transition="transition"
|
|
@animationfinish="animationfinish"
|
|
>
|
|
<swiper-item v-for="(item, index) in topicList">
|
|
<view class="content">
|
|
<view class="expose_shadow"></view>
|
|
<scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" :refresher-threshold="0">
|
|
<Subject
|
|
:item="item"
|
|
:mode="mode"
|
|
:isPreview="item.isPreview"
|
|
:clearResult="item.clearResult"
|
|
@subject_click="subject_click"
|
|
v-model="item.my_answer"
|
|
></Subject>
|
|
</scroll-view>
|
|
</view>
|
|
</swiper-item>
|
|
</swiper>
|
|
</view>
|
|
|
|
<view class="fixed-box font_pf" :style="{ marginBottom: popup_input_bottom }">
|
|
<view class="touch-btn-div" :class="{ show: showTouchBtn }">
|
|
<TouchBtnOnlyVoice
|
|
v-if="answerMethod === '03'"
|
|
class="talk-btns"
|
|
ref="touchBtnRef"
|
|
@uploadVoice="touchBtnSubmit('voice', $event)"
|
|
@submitAnswer="touchBtnSubmit('text', $event)"
|
|
:isLoading="touchIsDisabled"
|
|
loadingText="只能进行一条回答"
|
|
:adjustPosition="false"
|
|
:isDisabled="false"
|
|
:onlyVoice="true"
|
|
:answerMethod="answerMethod"
|
|
/>
|
|
<TouchBtn
|
|
v-else
|
|
class="talk-btns"
|
|
ref="touchBtnRef"
|
|
@uploadVoice="touchBtnSubmit('voice', $event)"
|
|
@submitAnswer="touchBtnSubmit('text', $event)"
|
|
:isLoading="touchIsDisabled"
|
|
loadingText="只能进行一条回答"
|
|
:adjustPosition="false"
|
|
:isDisabled="false"
|
|
:answerMethod="answerMethod"
|
|
|
|
/>
|
|
|
|
</view>
|
|
</view>
|
|
<!-- 反馈组件 -->
|
|
<Feedback ref="feedbackRef"></Feedback>
|
|
<!-- 结尾弹出层 -->
|
|
<Dialog ref="dialogRef" @button_click="result_click"></Dialog>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive, computed, onMounted, nextTick, onUnmounted } from 'vue';
|
|
import { onLoad, onHide, onShow, onUnload, onBackPress, onReady } from '@dcloudio/uni-app';
|
|
|
|
import Feedback from '@/pages/examination/components/feedback.vue';
|
|
import Dialog from '@/pages/examination/components/dialog.vue';
|
|
import Subject from '@/components/examination/subject.vue';
|
|
import CharactersSubject from '@/components/examination/characters-subject.vue';
|
|
// import TouchBtn from '@/components/examination/touchBtn.vue';
|
|
import TouchBtn from '@/pages/course/components/touchBtn.vue';
|
|
import TouchBtnOnlyVoice from '@/pages/course/components/touchBtnOnlyVoice.vue';
|
|
import common from '@/common/common';
|
|
import { setPageCache, formatSeconds, getPageCache, setupKeyboardHeightListener } from '@/common/common';
|
|
import { commonUploadVoiceFile } from '@/api/common.js';
|
|
import { optionErrorIcon, examinationSheetIcon, practiceExitIcon } from '@/common/imgSvg';
|
|
import { practiceAnswer, practiceCommit, queryCrsPracticeAnswerResult } from '@/api/practice.js';
|
|
import { startExamByCrs } from '@/api/examination.js';
|
|
import { startPracticeByCrs } from '@/api/practice.js';
|
|
const swiperRef = ref(null);
|
|
const feedbackRef = ref(null);
|
|
const dialogRef = ref(null);
|
|
const touchBtnRef = ref(null);
|
|
const answerMethod = ref('01');
|
|
const practiceTime = ref(0); // 当前练习时间
|
|
let practiceStartTime = 0; // 练习开始时间
|
|
let practiceTimeTimer = null; // 练习计时器
|
|
let leaveDuration = 0; // 当前总计离开时间
|
|
let leaveStartTime = 0; // 离开开始时间
|
|
const mode = ref('practice'); // 考试 examination 练习practice
|
|
const systemInfo = uni.getSystemInfoSync();
|
|
|
|
const paperData = reactive({
|
|
exrId: '',
|
|
crsId: '',
|
|
name: '' // 名称
|
|
}); // 试卷信息
|
|
const topicList = reactive([]); // 问题列表
|
|
const storageTopicList = ref([]); // 所有题列表
|
|
const popup_input_bottom = ref('0px');
|
|
const questionNumber = ref(0); // 题号
|
|
|
|
const topic = computed({
|
|
get: () => topicList[questionNumber.value],
|
|
set: (val) => (topicList[questionNumber.value] = val)
|
|
});
|
|
|
|
const showTouchBtn = computed(() => {
|
|
return topic.value?.qnsTyp === 'ES' && !topic.value?.my_answer.anserResult;
|
|
});
|
|
|
|
// 下面语音组件的禁用状态判断
|
|
const touchIsDisabled = computed(() => {
|
|
return topic.value?.es_status !== '' && topic.value?.es_status !== undefined;
|
|
});
|
|
|
|
const progress = computed(() => {
|
|
// 计算进度百分比(保留两位小数)
|
|
const total = storageTopicList.value.length;
|
|
if (total === 0) return 0;
|
|
const completed = questionNumber.value + 1;
|
|
return Math.min(Math.round((completed / total) * 10000) / 100, 100);
|
|
});
|
|
|
|
// 滑动切换
|
|
const swiperChange = (item) => {
|
|
questionNumber.value = item.detail.current;
|
|
};
|
|
const isTriggered = ref(false); // 下面这个得防抖
|
|
// 滑动发生改变
|
|
const finishCurrent = ref(questionNumber.value);
|
|
// 滑动组件结束事件
|
|
const animationfinish = (event) => {
|
|
finishCurrent.value = event.detail.current;
|
|
};
|
|
// 判断是否滑动结束
|
|
const isLastTopic = computed(
|
|
() => topicList.length === finishCurrent.value + 1 && finishCurrent.value === questionNumber.value
|
|
);
|
|
const showSwiper = ref(false);
|
|
const transition = (event) => {
|
|
if (isTriggered.value) return;
|
|
const dx = event.detail.dx;
|
|
if (dx > 80 && dx < 250 && isLastTopic.value && ['P', 'U'].includes(topic.value.judgeResult)) {
|
|
// 如果是最后一题并且右滑动大于50,并且这题已经答了,就触发练习完成
|
|
isTriggered.value = true;
|
|
hand_in_paper_button_click();
|
|
}
|
|
};
|
|
|
|
const subject_click = (type, params) => {
|
|
if (type === 'feedback') {
|
|
// 反馈
|
|
feedbackRef.value.open(params.qnsId);
|
|
} else if (type === 'answer') {
|
|
//多选点击按钮答题
|
|
if (params.qnsTyp === 'MU') {
|
|
submitProblem({
|
|
anserResult: params.answer.join(',')
|
|
});
|
|
}
|
|
} else if (type === 'choose') {
|
|
//单选判断点击选项答题
|
|
if (['JD', 'SN'].includes(params.qnsTyp)) {
|
|
submitProblem({ anserResult: params.answer.join(',') });
|
|
}
|
|
} else if (type === 'complete') {
|
|
// 问答题点击完成
|
|
submitProblem(params.answer);
|
|
} else if (type === 'again') {
|
|
// 问答题点击重答
|
|
topic.value.my_answer = {};
|
|
topic.value.isPreview = false;
|
|
topic.value.es_status = ''; // 取消转圈
|
|
}
|
|
};
|
|
|
|
// 单题回答
|
|
const submitProblem = (answer) => {
|
|
common.loading('答题中');
|
|
practiceAnswer({
|
|
exrId: paperData.exrId,
|
|
ossKey: '',
|
|
qnsId: topic.value.qnsId,
|
|
showOrder: questionNumber.value + 1,
|
|
examLenTm: practiceTime.value, // 练习时长
|
|
...answer
|
|
})
|
|
.then(async (res) => {
|
|
let traQnsInfoVo;
|
|
// 是问答题
|
|
if (topic.value.qnsTyp === 'ES') {
|
|
try {
|
|
const result = await queryWithRetry(res.body.execLogId);
|
|
traQnsInfoVo = result.body.traQnsInfoVo;
|
|
} catch (e) {
|
|
common.hideLoading();
|
|
topic.value.isPreview = false;
|
|
return;
|
|
}
|
|
} else {
|
|
traQnsInfoVo = res.body.traQnsInfoVo;
|
|
}
|
|
topic.value.isPreview = true; // 不能在点击了,打开预览模式
|
|
console.log('给出来的traQnsInfoVo', traQnsInfoVo);
|
|
common.hideLoading();
|
|
topic.value.clearResult = false; // 不清除正确答案
|
|
topic.value.analyContent = traQnsInfoVo.analyContent; // 答案解析
|
|
// 更新选项正确项目
|
|
topic.value.itemVos = traQnsInfoVo.itemVos; // 答案选项(todo应该不这样替换)
|
|
topic.value.anserResult = traQnsInfoVo.anserResult; // 正确答案字符串分割
|
|
topic.value.judgeResult = traQnsInfoVo.judgeResult; // 正确答案字符串分割
|
|
const judgeResultStatus = traQnsInfoVo.judgeResult === 'P'; // P为正确U为错误
|
|
if (!addProblem()) {
|
|
// 返回false说明到了最后一题
|
|
console.log('最后一题', topic.value.qnsTyp, !judgeResultStatus);
|
|
if (topic.value.qnsTyp === 'ES' || !judgeResultStatus) {
|
|
// 最后一题是问答题,或者答错了,都不自动弹出
|
|
return;
|
|
} else {
|
|
hand_in_paper_button_click();
|
|
return;
|
|
}
|
|
} else {
|
|
// 自动切换下一题的条件
|
|
if (
|
|
judgeResultStatus && // 条件1.答题正确
|
|
topic.value.qnsTyp !== 'ES' // 问答题答对打答错都不切换
|
|
) {
|
|
nextTick(() => {
|
|
setTimeout(() => {
|
|
questionNumber.value++;
|
|
}, 200);
|
|
});
|
|
}
|
|
}
|
|
})
|
|
.catch(() => {
|
|
// 单选和判断需要清除已点击的按钮
|
|
if (['JD', 'SN'].includes(topic.value.qnsTyp)) {
|
|
topic.value.my_answer = [];
|
|
}
|
|
common.hideLoading();
|
|
});
|
|
};
|
|
|
|
// 问答题轮询结果方法
|
|
const queryWithRetry = (execLogId, maxRetries = 10) => {
|
|
// 递归终止条件:达到最大重试次数
|
|
if (maxRetries <= 0) {
|
|
return Promise.reject(new Error('超过最大重试次数,查询失败'));
|
|
}
|
|
return queryCrsPracticeAnswerResult({ execLogId })
|
|
.then((res) => {
|
|
console.log('queryCrsPracticeAnswerResult', maxRetries, res.body);
|
|
const isWait = res.body.isWait;
|
|
if (isWait === 'Y') {
|
|
// 如果是Y,延迟2秒后重试,重试次数减1
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
resolve(queryWithRetry(execLogId, maxRetries - 1));
|
|
}, 2000);
|
|
});
|
|
} else {
|
|
// 不是Y,直接返回结果
|
|
return res;
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
// 对接口调用错误进行重试
|
|
if (maxRetries > 0) {
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
resolve(queryWithRetry(execLogId, maxRetries - 1));
|
|
}, 2000);
|
|
});
|
|
}
|
|
return Promise.reject(error);
|
|
});
|
|
};
|
|
|
|
// 录音组件提交
|
|
const touchBtnSubmit = (type, submitObj) => {
|
|
const topic = topicList[questionNumber.value];
|
|
touchBtnRef.value?.clearInputText(); // 清除发送框数据
|
|
if (type === 'voice') {
|
|
if (topic.es_status === '00') return;
|
|
topic.es_status = '00'; // 00转圈
|
|
const voicePath = submitObj;
|
|
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
|
|
.then((_res) => {
|
|
const _content = _res.body.transContent.trim();
|
|
if (_content === '') {
|
|
topic.es_status = ''; // 取消转圈
|
|
return common.msg('未识别到文字');
|
|
} else {
|
|
topic.es_status = '02';
|
|
topic.my_answer = {
|
|
anserResult: _res.body.transContent,
|
|
ossKey: _res.body.fileId,
|
|
ossAddr: _res.body.ossFileAddr,
|
|
voicePath: voicePath
|
|
};
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
topic.es_status = ''; // 取消转圈
|
|
if (error === 'Other') {
|
|
common.msg('系统异常,请联系管理员');
|
|
}
|
|
});
|
|
} else if (type === 'text') {
|
|
topic.es_status = '01';
|
|
topic.my_answer = {
|
|
anserResult: submitObj // 正确答案文字内容
|
|
};
|
|
}
|
|
};
|
|
|
|
// 添加一道题
|
|
const addProblem = () => {
|
|
if (topicList.length >= storageTopicList.value.length) {
|
|
return false;
|
|
}
|
|
topicList.push(storageTopicList.value[topicList.length]);
|
|
return true;
|
|
};
|
|
const examStat = ref('');
|
|
// 初始化时检查
|
|
onLoad((e) => {
|
|
examStat.value = e.examStat ?? '';
|
|
const practice = getPageCache('practice');
|
|
if (!practice) {
|
|
common.navigateBack();
|
|
return;
|
|
}
|
|
paperData.crsId = practice.crsId;
|
|
paperData.name = practice.name;
|
|
paperData.exrId = practice.exrId;
|
|
answerMethod.value = practice.answerMethod ?? '01';
|
|
storageTopicList.value = practice.qnsInfoVos.map((res) => ({
|
|
...res,
|
|
isPreview: false,
|
|
clearResult: true,
|
|
es_status: '', // 预设一下问答题的状态,'' 空为没有 00 转圈 01 播放,其他暂定
|
|
my_answer: [],
|
|
answerMethod: answerMethod.value
|
|
}));
|
|
addProblem();
|
|
// 记录练习起始时间
|
|
practiceStartTime = new Date().getTime();
|
|
setupKeyboardHeightListener((height) => {
|
|
popup_input_bottom.value = `${height}px`;
|
|
console.log('需要卸载吗');
|
|
});
|
|
});
|
|
const result_click = async ({ key }) => {
|
|
isTriggered.value = false; // 恢复
|
|
if (key === 'exit') {
|
|
// 中途退出
|
|
dialogRef.value.close();
|
|
common.loading();
|
|
try {
|
|
await practiceCommit({ exrId: paperData.exrId, examLenTm: practiceTime.value, stat: 'U' });
|
|
} catch (e) {}
|
|
common.navigateBack();
|
|
common.hideLoading();
|
|
} else if (key === 'revert') {
|
|
// 返回
|
|
dialogRef.value.close();
|
|
}
|
|
};
|
|
const style_button_1 = {
|
|
color: '#FFFFFF',
|
|
fontSize: '30rpx',
|
|
backgroundColor: '#0066FF',
|
|
borderRadius: '8rpx'
|
|
};
|
|
const style_button_2 = {
|
|
color: '#0066FF',
|
|
fontSize: '30rpx',
|
|
backgroundColor: '#E2EDFF',
|
|
borderRadius: '8rpx'
|
|
};
|
|
// 弹出框配置
|
|
const dialogConfiguration = reactive({});
|
|
// 交卷按钮点击,打开交卷确认框
|
|
const hand_in_paper_button_click = () => {
|
|
console.log('交卷按钮');
|
|
const stat = 'P';
|
|
showSwiper.value = true;
|
|
// 2. 延迟 50ms 确保 swiper 已销毁,再跳转
|
|
|
|
nextTick(() => {
|
|
common.redirectTo(
|
|
`/pages/practice/result?name=${paperData.name}&exrId=${paperData.exrId}&crsId=${paperData.crsId}&examLenTm=${practiceTime.value}&stat=${stat}&examStat=${examStat.value}`
|
|
);
|
|
});
|
|
};
|
|
// 中途退出
|
|
const exit_practice = () => {
|
|
dialogRef.value.open({
|
|
title: '确认现在退出吗?',
|
|
buttonList: [
|
|
{
|
|
key: 'exit',
|
|
name: '退出',
|
|
style: style_button_1
|
|
},
|
|
{
|
|
key: 'revert',
|
|
name: '返回',
|
|
style: style_button_2
|
|
}
|
|
]
|
|
});
|
|
};
|
|
// 启动练习时长定时器
|
|
const startTimer = () => {
|
|
if (practiceTimeTimer) {
|
|
clearInterval(practiceTimeTimer);
|
|
}
|
|
practiceTimeTimer = setInterval(() => {
|
|
const currentTime = Date.now();
|
|
const elapsedSeconds = Math.floor((currentTime - practiceStartTime - leaveDuration) / 1000);
|
|
practiceTime.value = elapsedSeconds;
|
|
}, 1000);
|
|
};
|
|
// 暂停定时器
|
|
const stopTimer = () => {
|
|
if (practiceTimeTimer) {
|
|
clearInterval(practiceTimeTimer);
|
|
practiceTimeTimer = null;
|
|
}
|
|
};
|
|
onShow(() => {
|
|
if (leaveStartTime) {
|
|
const time = Date.now() - leaveStartTime;
|
|
leaveDuration += time;
|
|
leaveStartTime = 0; // 重置离开开始时间
|
|
}
|
|
startTimer(); // 启动/恢复定时器
|
|
});
|
|
onHide(() => {
|
|
leaveStartTime = new Date().getTime();
|
|
stopTimer();
|
|
});
|
|
onUnload(() => {
|
|
stopTimer();
|
|
});
|
|
|
|
onBackPress((res) => {
|
|
if (res.from === 'backbutton') {
|
|
exit_practice();
|
|
return true;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
$bg-margin-left: 30rpx;
|
|
.popup_title_text {
|
|
color: red;
|
|
}
|
|
|
|
.popup {
|
|
//答题卡
|
|
z-index: 1800;
|
|
padding: 0 38rpx;
|
|
|
|
.sheet_popup_div {
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: #ffffff;
|
|
padding: 10rpx 34rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
border-radius: 16rpx 16rpx 0px 0px;
|
|
position: relative;
|
|
|
|
.title_div {
|
|
width: 100%;
|
|
text-align: center;
|
|
padding: 30rpx 0;
|
|
font-family: PingFangSC;
|
|
font-weight: 600;
|
|
font-size: 34rpx;
|
|
color: #000000;
|
|
text-align: center;
|
|
font-style: normal;
|
|
border-bottom: 2rpx solid #efefef;
|
|
}
|
|
|
|
.popup_back_div {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
position: absolute;
|
|
top: 30rpx;
|
|
right: 30rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.img {
|
|
width: 30rpx;
|
|
height: 30rpx;
|
|
}
|
|
}
|
|
|
|
.sheet_table {
|
|
margin-top: 48rpx;
|
|
margin-bottom: 48rpx;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
width: calc(100vw - 108rpx);
|
|
align-content: space-between;
|
|
|
|
.sheet_table_item {
|
|
width: calc((100vw - 108rpx) / 5 - 16rpx);
|
|
height: calc((100vw - 108rpx) / 5 - 16rpx);
|
|
margin: 8rpx;
|
|
border: 2rpx solid #e5e5e5;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 32rpx;
|
|
color: #999999;
|
|
}
|
|
|
|
.current {
|
|
background-color: rgba(0, 102, 255, 0.6);
|
|
border-color: #0066ff;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.completed {
|
|
// 已完成
|
|
background-color: rgba(0, 102, 255, 0.1);
|
|
border-color: #0066ff;
|
|
color: #0066ff;
|
|
}
|
|
|
|
.mark,
|
|
.completed.mark {
|
|
background-color: rgba(232, 181, 49, 0.1);
|
|
color: #e8b531;
|
|
border-color: #e8b531;
|
|
}
|
|
|
|
.current.mark {
|
|
// 已完成
|
|
background-color: rgba(0, 102, 255, 0.6);
|
|
color: #ffffff;
|
|
border-color: #e8b531;
|
|
}
|
|
}
|
|
|
|
.sheet_button {
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
.fixed-box {
|
|
position: fixed;
|
|
width: 100%;
|
|
left: 0;
|
|
bottom: 0;
|
|
border-radius: 16rpx 16rpx 0px 0px;
|
|
border: 2rpx solid #e5e5e5;
|
|
background: #ffffff;
|
|
}
|
|
|
|
.touch-btn-div {
|
|
height: 0;
|
|
overflow: hidden;
|
|
transition: height 0.2s ease-out;
|
|
}
|
|
|
|
.touch-btn-div.show {
|
|
height: 150rpx;
|
|
}
|
|
|
|
.fixed-btn-box {
|
|
height: 154rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 0 20rpx 20rpx 20rpx;
|
|
|
|
.sheet_button {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
margin: 0 70rpx;
|
|
|
|
.img {
|
|
width: 38rpx;
|
|
height: 40rpx;
|
|
}
|
|
|
|
.sheet_text {
|
|
margin-top: 8rpx;
|
|
font-family: PingFangSC;
|
|
font-weight: 500;
|
|
font-size: 24rpx;
|
|
color: #000000;
|
|
}
|
|
}
|
|
|
|
.button_div {
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
justify-content: space-between;
|
|
|
|
.button {
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.scroll-Y {
|
|
max-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx);
|
|
min-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx - 380rpx);
|
|
}
|
|
|
|
.swiper {
|
|
// 状态栏 var(--status-bar-height)
|
|
// 标题栏 70rpx
|
|
// 进度时间栏 70rpx
|
|
// 进度时间栏上下间距 40rpx = 20rpx + 20rpx
|
|
// 正文上下间距 64rpx
|
|
height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx);
|
|
// background-color: red;
|
|
}
|
|
|
|
.content {
|
|
position: relative;
|
|
margin: 32rpx $bg-margin-left;
|
|
border-radius: 16rpx;
|
|
padding: 34rpx 30rpx 34rpx 36rpx;
|
|
background-color: #fff;
|
|
|
|
.expose_shadow {
|
|
margin-left: 36rpx;
|
|
position: absolute;
|
|
bottom: -26rpx;
|
|
left: 0%;
|
|
width: calc(100% - 66rpx);
|
|
height: 28rpx;
|
|
background-color: #ffffff;
|
|
border-radius: 0 0 14rpx 14rpx;
|
|
opacity: 0.4;
|
|
z-index: 0;
|
|
// background-color: red;
|
|
}
|
|
}
|
|
|
|
.countdown-and-question-number-div {
|
|
margin: 20rpx $bg-margin-left;
|
|
height: 70rpx;
|
|
// background-color: red;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
z-index: 10;
|
|
|
|
.top {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
font-family: PingFangSC;
|
|
font-size: 26rpx;
|
|
color: #ffffff;
|
|
text-align: left;
|
|
font-style: normal;
|
|
}
|
|
|
|
.question {
|
|
display: flex;
|
|
align-items: center;
|
|
width: 242rpx;
|
|
flex-wrap: nowrap;
|
|
|
|
.grey {
|
|
margin-right: 8rpx;
|
|
}
|
|
|
|
.countdown_time {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
color: #ffffff;
|
|
font-weight: 600;
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
.grey {
|
|
color: #b6e2ff;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.bold {
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.nav-div {
|
|
position: relative;
|
|
.title {
|
|
margin: 0 calc($bg-margin-left + 90rpx);
|
|
height: 70rpx;
|
|
font-family: PingFangSC;
|
|
font-weight: 500;
|
|
font-size: 34rpx;
|
|
color: #ffffff;
|
|
text-align: center;
|
|
font-style: normal;
|
|
line-height: 70rpx;
|
|
}
|
|
|
|
.back_div {
|
|
position: absolute;
|
|
right: $bg-margin-left;
|
|
top: 0;
|
|
height: 70rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
.img {
|
|
width: 32rpx;
|
|
height: 32rpx;
|
|
}
|
|
.text {
|
|
color: #eaeaea;
|
|
font-size: 24rpx;
|
|
white-space: nowrap;
|
|
margin-left: 4rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.main_div {
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: linear-gradient(to top, #3480ff, #0066ff);
|
|
/* 确保背景占满整个视口高度 */
|
|
// min-height: 100vh;
|
|
margin: 0;
|
|
}
|
|
</style>
|