2026-05-09 10:34:51 +08:00

414 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import classroomInteractionApi from '@/api/classroomInteraction'
import { userStore } from '@/stores'
import { XMessage } from '@/hooks'
import dayjs from 'dayjs'
import sass from '@/utils/sass'
const { token } = userStore()
const OSS_URL = import.meta.env.VITE_OSS_URL
const leftBg = `url(${OSS_URL}/urm/classroomInteraction_left_bg.png) top/contain no-repeat`
const rightBg = `url(${OSS_URL}/urm/classroomInteraction_right_bg.svg) top/contain no-repeat`
const methodBg = `url(${OSS_URL}/urm/classroomInteraction_left_main_bg.svg) top/contain no-repeat`
const uploadLoading = ref(false)
const navList = [
{
value: 0,
label: '文本',
},
{
value: 1,
label: '拍照',
},
]
const submitForm = ref({
type: 0,
answer: '',
})
const answerType = ref({
text: '',
img: '',
})
const listLoading = ref(false)
const historyList = ref<any>([])
const textBoxRef = ref()
const textHeight = ref()
// 输入文本
function inputText() {
textHeight.value = textBoxRef.value.scrollHeight + 'px'
if (!answerType.value.text) {
textHeight.value = ''
}
}
function handleBeforeUpload(rawFile: any) {
const fileType = ['image/jpeg', 'image/png']
if (!fileType.includes(rawFile.type)) {
XMessage.error('上传格式不正确只支持JPG/PNG')
return false
}
if (rawFile.size / 1024 / 1024 > 5) {
XMessage.error('图片过大')
return false
}
uploadLoading.value = true
return true
}
function handleUploadSuccess(res: any, _file: any) {
answerType.value.img = res.data.filePath
uploadLoading.value = false
}
async function submitAnswer() {
submitForm.value.answer =
submitForm.value.type === 0 ? answerType.value.text.trim() : answerType.value.img
classroomInteractionApi
.addClassDetectionRecord(submitForm.value)
.then(res => {
getHistoryList()
answerType.value = {
text: '',
img: '',
}
textHeight.value = ''
})
.catch(err => {
XMessage.error(err.data.msg)
})
}
async function getHistoryList() {
listLoading.value = true
classroomInteractionApi
.getClassDetectionRecordList({ clientType: 0 })
.then(res => {
historyList.value = res.data.rows
listLoading.value = false
})
.catch(err => {
console.log(err)
listLoading.value = false
})
}
onActivated(() => {
getHistoryList()
})
</script>
<template>
<div class="classroom_box">
<div class="top"><BackBar leftText="随堂测试"></BackBar></div>
<div class="main">
<div class="main-left">
<!-- <SelectTab
v-model="submitForm.type"
:dataList="navList"
class="nav-tab"
></SelectTab> -->
<div class="method">
<div v-if="submitForm.type === 0" class="method-text">
<textarea
ref="textBoxRef"
v-model="answerType.text"
placeholder="输入文本"
placeholder-style="color:#99d609;"
auto-height
:maxlength="-1"
class="hidden_scroll textbox"
:style="{ height: textHeight }"
@input="inputText"
></textarea>
</div>
<div v-else class="upload">
<img v-if="answerType.img" :src="answerType.img" class="imgBox" />
<div v-else class="upload-btn">
<el-upload
class="add-image-btn pointer"
action="/api/main/sysFileInfo/tenUploadAll"
:data="{ type: 1 }"
:headers="{
Authorization: token,
'X-Tenant-Id': sass.platform.tenantId,
}"
accept="image/*"
:before-upload="handleBeforeUpload"
:on-success="handleUploadSuccess"
:show-file-list="false"
:disabled="uploadLoading"
>
<Btn
:disabled="uploadLoading"
width="386"
height="108"
size="48"
class="btn pointer"
>{{ uploadLoading ? '上传中' : '点击拍照' }}</Btn
>
</el-upload>
<span class="tip">请将试卷答案拍照上传</span>
</div>
</div>
</div>
<Btn
type="primary"
:width="386"
:height="108"
:size="48"
class="submit-btn"
@click="submitAnswer"
>
提交
</Btn>
</div>
<div class="main-right">
<div class="title">历史检测</div>
<div class="history hidden_scroll">
<Empty
v-if="historyList.length === 0"
:type="listLoading ? 'loading' : 'task'"
content="暂无历史检测"
></Empty>
<div v-else class="history-list">
<div
v-for="(i, idx) in historyList"
:key="idx"
:class="[
'history-list-item',
i.markResult === 1 ? 'correct' : i.markResult === 0 ? 'error' : null,
]"
>
<div class="status">
{{ i.markResult === 1 ? '正确' : i.markResult === 0 ? '错误' : '' }}
</div>
<div class="sub-answer">
<img v-if="i.type === 1" :src="i.answer" class="sub-answer-img" />
<div v-else class="sub-answer-text">
{{ i.answer }}
</div>
</div>
<div v-if="i.addDiamond && i.addExp" class="award">
<span class="award_icon">
<Icon name="diamond" width="36"></Icon>
<span class="number"> +0{{ i.addDiamond }}</span>
</span>
<span class="award_icon">
<Icon name="exp_nobg" width="36"></Icon>
<span class="number"> +0{{ i.addExp }}</span>
</span>
</div>
<div class="sub-time">
{{ dayjs(i.createTime).format('MM-DD HH:mm') }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.classroom_box {
width: 100%;
height: 100%;
position: relative;
@include main_bg;
.top {
position: absolute;
padding: 2.67vh 64px 0;
}
.main {
display: flex;
justify-content: space-between;
padding: 10.67vh 64px 3.33vh 64px;
height: calc(100% - 168px);
&-left {
position: relative;
width: 728px;
height: 86.08vh;
background: v-bind(leftBg);
.nav-tab {
position: absolute;
top: 9.83vh;
left: 50%;
transform: translateX(-50%);
width: 508px;
height: 4.83vh;
}
.method {
position: absolute;
top: 18.33vh;
left: 40px;
padding: 2vh;
width: 648px;
height: 50.83vh;
background: v-bind(methodBg);
&-text {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.textbox {
width: 100%;
max-height: 100%;
border: none;
background-color: transparent;
text-align: center;
overflow: auto;
word-break: break-all;
resize: none;
font-size: 2.67vh;
}
}
.upload {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.imgBox {
border-radius: 1.67vh;
width: 648px;
height: 50.83vh;
}
&-btn {
text-align: center;
.tip {
font-family: 'OPPO Sans';
margin-top: 1.33vh;
font-size: 2vh;
display: block;
color: #99d609;
}
}
}
}
.submit-btn {
position: absolute;
bottom: 4vh;
left: 50%;
transform: translateX(-50%);
}
}
&-right {
width: 1032px;
width: calc(100% - 728px - 32px);
height: 86vh;
background: v-bind(rightBg);
.title {
padding: 2vh 32px;
font-family: $font-special;
color: $font-color;
font-size: 3vh;
line-height: 4.5vh;
text-align: center;
}
.history {
margin-top: 1.33vh;
padding: 1.33vh 32px 0.67vh 32px;
height: calc(100% - 136px);
box-sizing: border-box;
&-list {
display: flex;
flex-wrap: wrap;
&-item {
position: relative;
margin: 0 24px 1.33vh 0;
padding: 1.33vh 20px 0.33vh 32px;
width: 472px;
height: 13.33vh;
border-radius: 1.67vh;
border: 0.33vh solid #bed5fe;
background-color: #fff;
&:nth-child(2n) {
margin-right: 0;
}
.status {
padding: 0.67vh 24px;
width: 112px;
height: 5.33vh;
font-family: $font-special;
position: absolute;
right: 0;
top: 0;
background-color: #fff;
border-radius: 0 1.67vh 0 1.67vh;
font-size: 2.67vh;
line-height: 4vh;
background-color: #f1f6fe;
}
.sub-answer {
margin-bottom: 1vh;
height: 7vh;
color: $font-color;
font-size: 2.67vh;
line-height: 3.5vh;
&-img {
width: 256px;
height: 7vh;
border-radius: 1.67vh;
}
&-text {
@include multiple_ellipsis(2);
margin-right: 152px;
word-wrap: break-word;
}
}
.sub-time {
position: absolute;
right: 20px;
bottom: 0.33vh;
font-family: OPPOSans;
font-size: 2vh;
line-height: 3vh;
color: $font-color;
}
.award {
display: flex;
position: absolute;
left: 32px;
bottom: 0.33vh;
font-family: $font-special;
font-size: 2vh;
color: $font-color;
&_icon {
display: flex;
align-items: center;
margin-right: 16px;
.number {
margin-left: 5px;
}
}
}
}
}
.error {
border-color: #f00a0a;
.status {
color: #f00a0a;
background: #ffbfbf;
}
}
.correct {
border-color: #2f8a5b;
.status {
color: #2f8a5b;
background: #a2fb6e;
}
}
}
}
}
}
</style>