|
|
|
<template>
|
|
|
|
<div :class="['panel', { active: visible }]"
|
|
|
|
id="panel">
|
|
|
|
<el-container class="scrollbar"
|
|
|
|
id="container"
|
|
|
|
v-show="visible">
|
|
|
|
<el-header id="header">
|
|
|
|
<div class="panel-header"
|
|
|
|
id="panelHeader">
|
|
|
|
<div class="project">
|
|
|
|
<div class="inline-center">
|
|
|
|
<p>实训项目</p>
|
|
|
|
<el-tooltip effect="dark"
|
|
|
|
content="点击右侧“下三角”按钮可切换实验项目"
|
|
|
|
placement="bottom">
|
|
|
|
<i class="info el-icon-warning"
|
|
|
|
style="margin-left: 10px"></i>
|
|
|
|
</el-tooltip>
|
|
|
|
</div>
|
|
|
|
<el-select v-model="projectId"
|
|
|
|
placeholder="请选择"
|
|
|
|
class="select"
|
|
|
|
:disabled="per != 0"
|
|
|
|
@change="selectProject"
|
|
|
|
style="flex: 1">
|
|
|
|
<el-option v-for="(item, i) in projectList"
|
|
|
|
:key="item.projectId"
|
|
|
|
:label="i + 1 + '. ' + item.projectName"
|
|
|
|
:value="item.projectId"></el-option>
|
|
|
|
</el-select>
|
|
|
|
</div>
|
|
|
|
<div class="item">
|
|
|
|
<div class="count">
|
|
|
|
实训{{ text }}时间 <span>{{ day }}</span>天 <span>{{ hour }}</span>小时 <span>{{ minutes }}</span>分 <span>{{ seconds }}</span>秒
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="item">
|
|
|
|
<div>
|
|
|
|
总得分:
|
|
|
|
<span class="total-score">{{ grade }}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<el-button @click="toReport"
|
|
|
|
v-if="isSubmit">查看实验报告</el-button>
|
|
|
|
<el-button class="reload"
|
|
|
|
@click="reload"
|
|
|
|
v-show="per == 0">重新开始</el-button>
|
|
|
|
<el-button type="primary"
|
|
|
|
class="submit btn"
|
|
|
|
@click="confirmSubmit"
|
|
|
|
:disabled="isSubmit || !projectList.length">提交</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-header>
|
|
|
|
<el-container id="infoContainer">
|
|
|
|
<el-aside id="aside"
|
|
|
|
width="30%">
|
|
|
|
<div class="aside-header">
|
|
|
|
<div :class="['p-title color', 'system' + $themeId]">
|
|
|
|
<i class="el-icon-s-order"></i>
|
|
|
|
<p>实验目标</p>
|
|
|
|
</div>
|
|
|
|
<div class="goal">
|
|
|
|
<div v-if="pd.experimentTargetType == 0 || !pd.experimentTargetType"
|
|
|
|
class="ql-editor"
|
|
|
|
v-html="pd.experimentTarget"></div>
|
|
|
|
|
|
|
|
<mavon-editor v-else
|
|
|
|
class="md"
|
|
|
|
v-model="pd.experimentTarget"
|
|
|
|
:ishljs="true"
|
|
|
|
:subfield="false"
|
|
|
|
:editable="false"
|
|
|
|
:toolbarsFlag="false"
|
|
|
|
:boxShadowStyle="none" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="aside-footer">
|
|
|
|
<div :class="['p-title color', 'system' + $themeId]">
|
|
|
|
<i class="el-icon-s-management"></i>
|
|
|
|
<p>实验任务</p>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<el-row>
|
|
|
|
<el-col :span="24">
|
|
|
|
<el-card shadow="never"
|
|
|
|
:border="false">
|
|
|
|
<el-table class="task-table"
|
|
|
|
:data="taskList"
|
|
|
|
:stripe="true">
|
|
|
|
<el-table-column type="index"></el-table-column>
|
|
|
|
<el-table-column prop="name"
|
|
|
|
label="判分点"
|
|
|
|
align="center"></el-table-column>
|
|
|
|
<el-table-column prop="score"
|
|
|
|
label="分值"
|
|
|
|
width="60"
|
|
|
|
align="center"></el-table-column>
|
|
|
|
<template v-if="!competitionId">
|
|
|
|
<el-table-column label="结果"
|
|
|
|
width="60"
|
|
|
|
align="center">
|
|
|
|
<template v-slot="scope">
|
|
|
|
<template v-if="isSubmit">
|
|
|
|
<template v-if="!competitionId">
|
|
|
|
<i v-if="scope.row.finishedResult"
|
|
|
|
class="el-icon-check right"></i>
|
|
|
|
<i v-else
|
|
|
|
class="el-icon-close wrong"></i>
|
|
|
|
</template>
|
|
|
|
<template v-else>-</template>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column prop="score"
|
|
|
|
label="得分"
|
|
|
|
width="60"
|
|
|
|
align="center">
|
|
|
|
<template v-slot="scope">
|
|
|
|
<template v-if="isSubmit">{{ competitionId ? '-' : scope.row.examScore }}</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</template>
|
|
|
|
</el-table>
|
|
|
|
</el-card>
|
|
|
|
</el-col>
|
|
|
|
</el-row>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-aside>
|
|
|
|
<el-main id="main">
|
|
|
|
<el-tabs class="info-tab"
|
|
|
|
v-model="pannelTab"
|
|
|
|
type="card">
|
|
|
|
<el-tab-pane label="项目背景"
|
|
|
|
name="first">
|
|
|
|
<div v-if="pd.experimentDescriptionType == 0 || !pd.experimentDescriptionType"
|
|
|
|
class="ql-editor"
|
|
|
|
v-html="pd.experimentDescription"></div>
|
|
|
|
|
|
|
|
<mavon-editor v-else
|
|
|
|
class="md"
|
|
|
|
v-model="pd.experimentDescription"
|
|
|
|
:ishljs="true"
|
|
|
|
:subfield="false"
|
|
|
|
:editable="false"
|
|
|
|
:toolbarsFlag="false"
|
|
|
|
:boxShadowStyle="none" />
|
|
|
|
</el-tab-pane>
|
|
|
|
<el-tab-pane label="实验要求"
|
|
|
|
name="second">
|
|
|
|
<el-collapse v-model="curReq">
|
|
|
|
<el-collapse-item v-for="item in points"
|
|
|
|
:name="item.judgmentId"
|
|
|
|
:key="item.judgmentId">
|
|
|
|
<template v-slot:title>
|
|
|
|
<i class="el-icon-s-ticket"></i>
|
|
|
|
<div class="break-all des"
|
|
|
|
v-html="item.name"></div>
|
|
|
|
</template>
|
|
|
|
<div v-if="item.experimentalRequirementsType == 0 || !item.experimentalRequirementsType"
|
|
|
|
class="ql-editor"
|
|
|
|
v-html="item.experimentalRequirements"></div>
|
|
|
|
|
|
|
|
<mavon-editor v-else
|
|
|
|
class="md"
|
|
|
|
v-model="item.experimentalRequirements"
|
|
|
|
:ishljs="true"
|
|
|
|
:subfield="false"
|
|
|
|
:editable="false"
|
|
|
|
:toolbarsFlag="false"
|
|
|
|
:boxShadowStyle="none" />
|
|
|
|
</el-collapse-item>
|
|
|
|
</el-collapse>
|
|
|
|
</el-tab-pane>
|
|
|
|
<el-tab-pane label="实验提示"
|
|
|
|
name="third"
|
|
|
|
v-if="hintOpen">
|
|
|
|
<div v-if="pd.experimentHintType == 0 || !pd.experimentHintType"
|
|
|
|
class="ql-editor"
|
|
|
|
v-html="pd.experimentHint"></div>
|
|
|
|
|
|
|
|
<mavon-editor v-else
|
|
|
|
class="md"
|
|
|
|
v-model="pd.experimentHint"
|
|
|
|
:ishljs="true"
|
|
|
|
:subfield="false"
|
|
|
|
:editable="false"
|
|
|
|
:toolbarsFlag="false"
|
|
|
|
:boxShadowStyle="none" />
|
|
|
|
</el-tab-pane>
|
|
|
|
</el-tabs>
|
|
|
|
</el-main>
|
|
|
|
</el-container>
|
|
|
|
</el-container>
|
|
|
|
|
|
|
|
<div :class="['toggle-panel', { active: visible }]"
|
|
|
|
id="toggle"
|
|
|
|
@click="visible = !visible">
|
|
|
|
<!-- <div @click="togglePannel"> -->
|
|
|
|
<div>
|
|
|
|
<img :src="require(`@/assets/images/panel/left.png`)"
|
|
|
|
alt
|
|
|
|
class="c-p"
|
|
|
|
v-if="visible" />
|
|
|
|
<img :src="require(`@/assets/images/panel/right.png`)"
|
|
|
|
alt
|
|
|
|
class="c-p"
|
|
|
|
v-if="!visible" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { ref, onMounted, toRefs } from 'vue';
|
|
|
|
import { pageStuAssessment, getProjectBySystemId, getProjectDetail, getDetailById, getCompetition } from '@/api/system';
|
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
|
|
|
|
import Cookie from 'js-cookie';
|
|
|
|
import util from '@/libs/util';
|
|
|
|
import Setting from '@/setting';
|
|
|
|
// import { mavonEditor } from 'mavon-editor'
|
|
|
|
// import 'mavon-editor/dist/css/index.css'
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
const route = useRoute();
|
|
|
|
const { systemId, classId, courseId, projectId, assessmentId, competitionId, stageId, teamId, mallId } = toRefs(route.query);
|
|
|
|
const curSystemId = ref<number>(1);
|
|
|
|
const per = ref<number>(assessmentId.value ? 1 : competitionId.value ? 2 : 0); // 项目权限(0、练习 1、考核 2、竞赛)
|
|
|
|
const isSubmit = ref<boolean>(Cookie.get('st-isSubmit') === 'true'); // 是否提交的标识
|
|
|
|
const entryTime = ref<any>(new Date());
|
|
|
|
const visible = ref<boolean>(true);
|
|
|
|
const grade = ref<string | number>('00');
|
|
|
|
const text = ref<string>(''); // 倒计时前面的文字,练习:所用;考核:剩余。练习是计时,考核是倒计时
|
|
|
|
const counterTimer = ref<any>(null);
|
|
|
|
const day = ref<number | string>(0);
|
|
|
|
const seconds = ref<number | string>(0);
|
|
|
|
const minutes = ref<number | string>(0);
|
|
|
|
const hour = ref<number | string>(0);
|
|
|
|
const projectList = ref<Record<string, any>[]>([]);
|
|
|
|
const pd = ref<Record<string, any>>({});
|
|
|
|
const hintOpen = ref<string>('');
|
|
|
|
const points = ref<Record<string, any>[]>([]);
|
|
|
|
const judgmentId = ref<string | number>('');
|
|
|
|
const curReq = ref<Record<string, any>[]>([]);
|
|
|
|
const taskList = ref<Record<string, any>[]>([]);
|
|
|
|
const pannelTab = ref<string>('first');
|
|
|
|
const isSelected = ref<boolean>(false); // 是否选择过项目的标识,选择了会置为true
|
|
|
|
const statusTimer = ref<any>(null);
|
|
|
|
const reportId = ref<string | number>('');
|
|
|
|
let countVal = <any>'';
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
assessmentId.value && getAssList();
|
|
|
|
if (competitionId.value) {
|
|
|
|
clearInterval(statusTimer);
|
|
|
|
statusTimer.value = setInterval((_) => {
|
|
|
|
getCompetitionStatus();
|
|
|
|
}, 1000);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// 获取项目列表
|
|
|
|
const getList = () => {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
const { projects } = await getProjectBySystemId({
|
|
|
|
systemId: systemId.value,
|
|
|
|
cId: courseId.value,
|
|
|
|
mallId: mallId.value,
|
|
|
|
permissions: per.value,
|
|
|
|
});
|
|
|
|
projectList.value = projects;
|
|
|
|
if (!per.value && !projectId.value) projectId.value = projects[0]?.projectId ?? 0; // 默认取第一个项目
|
|
|
|
getProDetail()
|
|
|
|
.then(() => {
|
|
|
|
resolve();
|
|
|
|
})
|
|
|
|
.catch((res) => {
|
|
|
|
reject();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// 获取项目详情
|
|
|
|
const getProDetail = () => {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
const res = await getProjectDetail({
|
|
|
|
projectId: projectId.value,
|
|
|
|
stuAssessent: 1,
|
|
|
|
});
|
|
|
|
const points = res.projectJudgmentVos;
|
|
|
|
const project = res.projectManage;
|
|
|
|
// 考核/竞赛
|
|
|
|
if (per.value) {
|
|
|
|
projectList.value = [
|
|
|
|
{
|
|
|
|
projectId: projectId.value,
|
|
|
|
projectName: project.projectName,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
}
|
|
|
|
curReq.value = points.map((e) => e.judgmentId); // 实验要求默认全部展开,通过judgmentId来选中item
|
|
|
|
points.value = points;
|
|
|
|
taskList.value = points; // 实验任务
|
|
|
|
judgmentId.value = points[0].judgmentId; // 默认取第一个判分点
|
|
|
|
pd.value = project;
|
|
|
|
hintOpen.value = project.founder ? !project.hintOpenBySchool : !project.hintOpen; // 0显示,1不显示,系统跟老师的禁用字段不一样
|
|
|
|
const isPrac = per.value === 0; // 是否是练习
|
|
|
|
text.value = isPrac ? '已用' : '剩余';
|
|
|
|
// 竞赛不需要
|
|
|
|
if (!competitionId.value) {
|
|
|
|
countVal = isPrac ? 0 : (new Date(endTime.value).getTime() - Date.now()) / 1000; // 如果是考核,取考核的结束时间减去当前时间去做倒计时,练习则直接给0做计时
|
|
|
|
startCount();
|
|
|
|
}
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// 设置isSubmit
|
|
|
|
// setSubmit(status) {
|
|
|
|
// this.isSubmit = status;
|
|
|
|
// newmain.$emit('isSubmit', status);
|
|
|
|
// Cookie.set('admin-isSubmit', status);
|
|
|
|
// },
|
|
|
|
// 获取考核列表来查询该考核是否已经考过
|
|
|
|
const getAssList = async () => {
|
|
|
|
const { list } = await pageStuAssessment({
|
|
|
|
pageNum: 1,
|
|
|
|
pageSize: 10000,
|
|
|
|
});
|
|
|
|
let done = false;
|
|
|
|
// 匹配到该考核,并且已经提交过(有reportId则说明有实验记录),并且classId跟当前用户的classId相同,就提示提交了考核然后返回上一页
|
|
|
|
if (list.find((e) => e.assessmentId == assessmentId.value && e.reportId && e.classId == classId.value)) {
|
|
|
|
done = true;
|
|
|
|
setSubmit(true);
|
|
|
|
ElMessage.error('你已经提交过该考核!');
|
|
|
|
setTimeout((_) => {
|
|
|
|
window.history.back(); // 直接返回上一页面
|
|
|
|
}, 1500);
|
|
|
|
}
|
|
|
|
statusTimer.value = setInterval((_) => {
|
|
|
|
getAssStatus();
|
|
|
|
}, 1000);
|
|
|
|
};
|
|
|
|
// 定时查询考核状态(查到考核如果结束后,直接提交考核)
|
|
|
|
const getAssStatus = async () => {
|
|
|
|
// 未提交才需要查询状态
|
|
|
|
if (!isSubmit.value) {
|
|
|
|
const { data } = await getDetailById(assessmentId.value);
|
|
|
|
const done = data ? data.status === 2 : false; // 状态(0、待开始 1、进行中 2、已结束)
|
|
|
|
// 如果考核已结束,则清除查询考核状态的定时器,并且自动提交
|
|
|
|
if (done) {
|
|
|
|
clearInterval(statusTimer.value);
|
|
|
|
// this.$alert('考核时间已到,系统已自动交卷', '提示', {
|
|
|
|
// confirmButtonText: '确定',
|
|
|
|
// });
|
|
|
|
submit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 定时查询竞赛状态(查到竞赛如果结束后,直接提交竞赛)
|
|
|
|
const getCompetitionStatus = async () => {
|
|
|
|
// 未提交才需要查询状态
|
|
|
|
if (!isSubmit.value) {
|
|
|
|
const { competition } = await getCompetition(competitionId.value);
|
|
|
|
const stages = competition.competitionStage;
|
|
|
|
if (stages) {
|
|
|
|
const stage = stages.find((e) => e.stageId == stageId.value);
|
|
|
|
const endTime = new Date(stage.endTime).getTime();
|
|
|
|
const now = Date.now();
|
|
|
|
// 如果已经结束
|
|
|
|
if (now >= new Date(stage.endTime)) {
|
|
|
|
clearInterval(statusTimer.value);
|
|
|
|
// this.$alert('竞赛时间已到,系统已自动交卷', '提示', {
|
|
|
|
// confirmButtonText: '确定',
|
|
|
|
// });
|
|
|
|
submit();
|
|
|
|
} else {
|
|
|
|
// 没结束,则显示倒计时(竞赛才需要通过定时调接口来显示倒计时,因为中台可以修改结束时间,所以需要时刻获取最新的结束时间)
|
|
|
|
counter((endTime - now) / 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// 项目选择回调
|
|
|
|
const selectProject = () => {
|
|
|
|
isSelected.value = true;
|
|
|
|
getProDetail();
|
|
|
|
// setSubmit(false);
|
|
|
|
countVal.value = 0;
|
|
|
|
grade.value = '00';
|
|
|
|
pannelTab.value = 'first';
|
|
|
|
clearReport();
|
|
|
|
};
|
|
|
|
// 重新开始
|
|
|
|
const reload = () => {
|
|
|
|
reloadCount();
|
|
|
|
grade.value = '00';
|
|
|
|
// this.setSubmit(false);
|
|
|
|
startCount();
|
|
|
|
};
|
|
|
|
// 提交
|
|
|
|
const submit = () => {
|
|
|
|
ElMessageBox.confirm('此操作将视为结束考试,是否继续?', '提示', {
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
type: 'warning',
|
|
|
|
})
|
|
|
|
.then(() => {})
|
|
|
|
.catch(() => {});
|
|
|
|
|
|
|
|
// if (isSubmit.value) return false;
|
|
|
|
// const date = new Date();
|
|
|
|
// const timeSum = Math.ceil((date.getTime() - entryTime.getTime()) / 60000); // 计算实验用时(分钟),向上取整
|
|
|
|
// const submitTime = util.formatDate('yyyy-MM-dd hh:mm:ss', date);
|
|
|
|
// const { projectId } = this;
|
|
|
|
// const pro = this.projectList.find((e) => e.projectId == projectId);
|
|
|
|
// const projectName = pro ? pro.projectName : ''; // 获取项目名称
|
|
|
|
// this.reloadCount();
|
|
|
|
// // 判分点参数
|
|
|
|
// const attributesReqList = [];
|
|
|
|
// pointList.map((e) => {
|
|
|
|
// attributesReqList.push({
|
|
|
|
// codeId: e.codeId,
|
|
|
|
// bcId: e.judgmentId,
|
|
|
|
// isSubmit: e.codeId ? 1 : 0,
|
|
|
|
// answer: e.answer,
|
|
|
|
// retResult: e.retResult,
|
|
|
|
// });
|
|
|
|
// });
|
|
|
|
// const data = {
|
|
|
|
// classId: this.classId ? this.classId : '',
|
|
|
|
// className: this.className ? this.className : '',
|
|
|
|
// curriculumId: this.courseId,
|
|
|
|
// startTime: this.per ? this.startTime : util.formatDate('yyyy-MM-dd hh:mm:ss', entryTime), // 开始时间(考核:直接从职站取考核的开始时间;练习:取页面进入的时间)
|
|
|
|
// endTime: this.per ? this.endTime : submitTime, // 结束时间(考核:直接从职站取考核的结束时间;练习:取提交时间)
|
|
|
|
// submitTime, // 提交时间,即当前时间(这3个时间都是传完整的日期时间格式)
|
|
|
|
// timeSum,
|
|
|
|
// projectId,
|
|
|
|
// projectName,
|
|
|
|
// assessmentId: this.assessmentId ? this.assessmentId : '',
|
|
|
|
// totalScore: 100, // 判分点总分固定为100
|
|
|
|
// systemId: this.curSystemId,
|
|
|
|
// purpose: this.pd.experimentTarget, // 实验目的
|
|
|
|
// attributesReqList,
|
|
|
|
// competitionId: this.competitionId,
|
|
|
|
// stageId: this.stageId,
|
|
|
|
// teamId: this.teamId,
|
|
|
|
// mallId: this.mallId,
|
|
|
|
// };
|
|
|
|
// this.$post(this.api.submit, data)
|
|
|
|
// .then(({ retInfo, reportId }) => {
|
|
|
|
// localStorage.removeItem('codeCache');
|
|
|
|
// this.setSubmit(true);
|
|
|
|
// clearInterval(this.statusTimer);
|
|
|
|
// this.reportVisible = false;
|
|
|
|
// const list = retInfo;
|
|
|
|
// const { taskList } = this;
|
|
|
|
// let score = 0;
|
|
|
|
// // 给判分列表添加分数和运行结果
|
|
|
|
// taskList.map((e) => {
|
|
|
|
// const item = list.find((n) => n.judgmentPointsId === e.judgmentId);
|
|
|
|
// if (item) {
|
|
|
|
// e.examScore = item.score;
|
|
|
|
// e.finishedResult = item.finishedResult; // 1:正确,2:错误
|
|
|
|
// } else {
|
|
|
|
// e.examScore = 0;
|
|
|
|
// }
|
|
|
|
// score += e.examScore; // 计算总分
|
|
|
|
// });
|
|
|
|
// this.grade = util.handleZero(score); // 前置加0(竞赛不显示分数)
|
|
|
|
// this.reportId = reportId;
|
|
|
|
// this.$store.commit('setReportId', reportId);
|
|
|
|
// this.$store.commit('setTaskList', taskList);
|
|
|
|
// this.editReport(reportId);
|
|
|
|
// // 如果是竞赛,并且勾选了公布成绩详情的选项,则弹框提示
|
|
|
|
// this.competitionId &&
|
|
|
|
// this.resultsDetails == 0 &&
|
|
|
|
// this.$alert(`提交成功${this.resultAnnouncementTime != 0 ? `,成绩将在${this.resultAnnouncementTime}小时后发布,请去参赛信息模块查看` : ''}`, '提示', {
|
|
|
|
// confirmButtonText: '确定',
|
|
|
|
// callback: (action) => {
|
|
|
|
// this.$parent.back();
|
|
|
|
// },
|
|
|
|
// });
|
|
|
|
// })
|
|
|
|
// .catch((err) => {});
|
|
|
|
};
|
|
|
|
// 倒计时
|
|
|
|
const timeFormat = (num: number): string | number => {
|
|
|
|
return num < 10 ? `0${num}` : num;
|
|
|
|
};
|
|
|
|
// 清除时间
|
|
|
|
const reloadCount = () => {
|
|
|
|
clearInterval(counterTimer.value);
|
|
|
|
countVal.value = '';
|
|
|
|
day.value = '00';
|
|
|
|
seconds.value = '00';
|
|
|
|
minutes.value = '00';
|
|
|
|
hour.value = '00';
|
|
|
|
};
|
|
|
|
// 计时器(考核是倒计时,练习是计时)
|
|
|
|
const counter = (counterTime: number) => {
|
|
|
|
const leave1 = counterTime % (24 * 3600); // 计算天数后剩余的毫秒数
|
|
|
|
const leave2 = leave1 % 3600; // 计算小时数后剩余的毫秒数
|
|
|
|
const leave3 = leave2 % 60; // 计算分钟数后剩余的毫秒数
|
|
|
|
|
|
|
|
day.value = timeFormat(Math.floor(counterTime / (24 * 3600)));
|
|
|
|
hour.value = timeFormat(Math.floor(leave1 / 3600));
|
|
|
|
minutes.value = timeFormat(Math.floor(leave2 / 60));
|
|
|
|
seconds.value = timeFormat(Math.round(leave3));
|
|
|
|
};
|
|
|
|
// 启动倒计时
|
|
|
|
const startCount = () => {
|
|
|
|
clearInterval(counterTimer.value);
|
|
|
|
counterTimer.value = setInterval(() => {
|
|
|
|
counter(per.value ? countVal.value-- : countVal.value++);
|
|
|
|
}, 1000);
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.el-main {
|
|
|
|
width: 60%;
|
|
|
|
background-color: #fff;
|
|
|
|
color: #333;
|
|
|
|
padding: 0;
|
|
|
|
font-size: 16px;
|
|
|
|
margin: 0px 20px 10px 10px;
|
|
|
|
white-space: pre-wrap;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
.panel-header {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
|
|
|
.project {
|
|
|
|
display: inline-flex;
|
|
|
|
align-items: center;
|
|
|
|
width: 28%;
|
|
|
|
}
|
|
|
|
.item {
|
|
|
|
font-size: 16px;
|
|
|
|
margin: 0 10px;
|
|
|
|
padding: 20px 0;
|
|
|
|
}
|
|
|
|
.count {
|
|
|
|
margin-left: -40px;
|
|
|
|
span {
|
|
|
|
padding: 5px 15px;
|
|
|
|
margin: 0 5px;
|
|
|
|
color: #333;
|
|
|
|
font-size: 14px;
|
|
|
|
text-align: center;
|
|
|
|
background: #fff;
|
|
|
|
border-radius: 18px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.total-score {
|
|
|
|
padding: 10px;
|
|
|
|
font-size: 14px;
|
|
|
|
text-align: center;
|
|
|
|
border-radius: 6px;
|
|
|
|
}
|
|
|
|
.submit {
|
|
|
|
width: 106px;
|
|
|
|
font-size: 16px;
|
|
|
|
}
|
|
|
|
.reload {
|
|
|
|
color: #d0d0d0;
|
|
|
|
font-size: 16px;
|
|
|
|
background-color: #202020;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/deep/.des {
|
|
|
|
font-size: 16px;
|
|
|
|
font-family: 'Microsoft YaHei';
|
|
|
|
img {
|
|
|
|
max-width: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/deep/.el-collapse-item__wrap {
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
/deep/.el-collapse-item__header {
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
/deep/.el-icon-s-ticket:before {
|
|
|
|
padding: 5px;
|
|
|
|
font-size: 16px;
|
|
|
|
}
|
|
|
|
/deep/.el-collapse-item__arrow {
|
|
|
|
margin: 0 5px 0 0;
|
|
|
|
}
|
|
|
|
/deep/.info-tab.el-tabs--card {
|
|
|
|
.el-tabs__item {
|
|
|
|
font-size: 16px;
|
|
|
|
}
|
|
|
|
.el-tabs__item.is-active {
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
.el-tabs__header .el-tabs__nav {
|
|
|
|
border: none;
|
|
|
|
}
|
|
|
|
.el-tabs__header .el-tabs__item {
|
|
|
|
border-left: none;
|
|
|
|
}
|
|
|
|
.el-tabs__header {
|
|
|
|
padding: 5px 20px;
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
& > .el-tabs__content {
|
|
|
|
margin: 0 20px;
|
|
|
|
max-height: calc(60vh - 70px);
|
|
|
|
overflow: auto;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/deep/.el-collapse {
|
|
|
|
border-bottom: none;
|
|
|
|
border-top: none;
|
|
|
|
}
|
|
|
|
.el-aside {
|
|
|
|
margin-bottom: 10px;
|
|
|
|
color: #333;
|
|
|
|
background-color: #fff;
|
|
|
|
}
|
|
|
|
.el-aside /deep/[class*=' el-icon-'],
|
|
|
|
[class^='el-icon-'] {
|
|
|
|
line-height: 40px;
|
|
|
|
font-size: 16px;
|
|
|
|
}
|
|
|
|
.aside-header {
|
|
|
|
margin: 0px 10px 10px 10px;
|
|
|
|
background-color: #fff;
|
|
|
|
}
|
|
|
|
.aside-footer {
|
|
|
|
margin: 0px 10px 10px 10px;
|
|
|
|
background-color: #fff;
|
|
|
|
}
|
|
|
|
.p-title {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
height: 40px;
|
|
|
|
&.system4 {
|
|
|
|
background-size: 100% 58px;
|
|
|
|
}
|
|
|
|
&.system7,
|
|
|
|
&.system9 {
|
|
|
|
background-size: 100% 40px;
|
|
|
|
}
|
|
|
|
&.system8,
|
|
|
|
&.system6 {
|
|
|
|
background-size: 100% 61px;
|
|
|
|
}
|
|
|
|
p {
|
|
|
|
padding-left: 10px;
|
|
|
|
line-height: 40px;
|
|
|
|
font-size: 16px;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
i {
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/deep/.el-card__body {
|
|
|
|
padding: 0;
|
|
|
|
}
|
|
|
|
/deep/.task-table {
|
|
|
|
font-size: 12px;
|
|
|
|
thead {
|
|
|
|
color: #fff;
|
|
|
|
font-size: 10px;
|
|
|
|
}
|
|
|
|
th > .cell {
|
|
|
|
font-weight: 100;
|
|
|
|
}
|
|
|
|
td,
|
|
|
|
th.is-leaf {
|
|
|
|
border-bottom: 0 !important;
|
|
|
|
}
|
|
|
|
.el-table__cell {
|
|
|
|
padding: 6px 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.goal {
|
|
|
|
padding: 10px 0;
|
|
|
|
margin: 0 10px;
|
|
|
|
font-size: 14px;
|
|
|
|
}
|
|
|
|
/deep/.select {
|
|
|
|
.el-select__caret:before {
|
|
|
|
content: '\e78f';
|
|
|
|
padding: 3px;
|
|
|
|
font-size: 16px;
|
|
|
|
color: #fff;
|
|
|
|
border-radius: 50%;
|
|
|
|
}
|
|
|
|
.el-input__icon {
|
|
|
|
line-height: 60px;
|
|
|
|
}
|
|
|
|
.el-input {
|
|
|
|
padding: 10px 0;
|
|
|
|
}
|
|
|
|
.el-input--suffix .el-input__inner {
|
|
|
|
height: 40px !important;
|
|
|
|
padding-right: 50px;
|
|
|
|
margin-left: 15px;
|
|
|
|
color: #333;
|
|
|
|
font-size: 14px;
|
|
|
|
border-radius: 30px;
|
|
|
|
border: none;
|
|
|
|
background-color: #fff;
|
|
|
|
overflow: hidden;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
white-space: nowrap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.panel {
|
|
|
|
z-index: 1000;
|
|
|
|
position: relative;
|
|
|
|
top: 200px;
|
|
|
|
bottom: 20px;
|
|
|
|
left: 0;
|
|
|
|
width: 0;
|
|
|
|
height: 0;
|
|
|
|
.toggle-panel {
|
|
|
|
position: absolute;
|
|
|
|
top: 60%;
|
|
|
|
&.active {
|
|
|
|
left: 100%;
|
|
|
|
}
|
|
|
|
img {
|
|
|
|
height: 150px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
&.active {
|
|
|
|
position: fixed;
|
|
|
|
width: 85%;
|
|
|
|
height: 70%;
|
|
|
|
.toggle-panel {
|
|
|
|
top: 38%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/deep/.el-container {
|
|
|
|
height: 100%;
|
|
|
|
&.is-vertical {
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.right {
|
|
|
|
color: #00af00;
|
|
|
|
font-size: 20px;
|
|
|
|
}
|
|
|
|
.wrong {
|
|
|
|
color: #f00;
|
|
|
|
font-size: 20px;
|
|
|
|
}
|
|
|
|
.info {
|
|
|
|
color: #bfbfbf;
|
|
|
|
cursor: pointer;
|
|
|
|
&:hover {
|
|
|
|
opacity: 0.9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|