|
|
@@ -0,0 +1,231 @@
|
|
|
+<template>
|
|
|
+ <el-card class="test" shadow="hover" @click="toTestInfo">
|
|
|
+
|
|
|
+ <div :style="{borderBottom: type==='eval' ? '30px solid #f5b86e' : '30px solid #8dc9e2'}"
|
|
|
+ style="float: right; width: 0; height: 0; position: absolute;right: 0;bottom: 0;border-left: 30px solid transparent;">
|
|
|
+ <div v-if="type==='eval'" style="padding: 0 4px 0 4px; position: absolute; right: 0; bottom: -30px; color: white">
|
|
|
+ E
|
|
|
+ </div>
|
|
|
+ <div v-else style="padding: 0 3px 0 3px; position: absolute; right: 0; bottom: -30px; color: white">
|
|
|
+ C
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="16">
|
|
|
+ <el-col v-if="type==='eval'" class="title">
|
|
|
+ {{ testVO.examName }}
|
|
|
+ </el-col>
|
|
|
+ <el-col v-else class="title">
|
|
|
+ {{ testVO.name }}
|
|
|
+ </el-col>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8" class="status">
|
|
|
+ <el-tag v-if="state==='NOT_STARTED'" size="small" type="info">未开始</el-tag>
|
|
|
+ <el-tag v-else-if="state==='RUNNING'" size="small">进行中</el-tag>
|
|
|
+ <el-tag v-else-if="state==='FINISHED'" size="small" type="danger">已结束</el-tag>
|
|
|
+ <el-tag v-else-if="state==='CLOSED'" size="small" type="info">已关闭</el-tag>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col v-if="type==='eval'" class="course">
|
|
|
+ 所属课程: eval course
|
|
|
+ </el-col>
|
|
|
+ <el-col v-else class="course">
|
|
|
+ 所属课程: {{ testVO.course }}
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col v-if="type==='eval'" class="teacher">
|
|
|
+ 教师: {{ teacher.name }}
|
|
|
+ </el-col>
|
|
|
+ <el-col v-else class="teacher">
|
|
|
+ 教师: {{ testVO.creator.username }}
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col v-if="type==='eval'" class="time">
|
|
|
+ 时间: {{ testVO.startTime.substring(0, 16) }} 至 {{ testVO.endTime.substring(0, 16) }}
|
|
|
+ </el-col>
|
|
|
+ <el-col v-else class="time">
|
|
|
+ {{ timestampToTime(testVO.startAt) }} 至 {{ timestampToTime(testVO.endAt) }}
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row v-if="type==='eval'" class="comment">
|
|
|
+ {{ testVO.comment }}
|
|
|
+ </el-row>
|
|
|
+ </el-card>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { ElMessageBox } from "element-plus";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "TestCard",
|
|
|
+ props: {
|
|
|
+ testVO: Object,
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ teacher: {
|
|
|
+ type: Object,
|
|
|
+ default: {
|
|
|
+ name: "暂无信息",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ type() {
|
|
|
+ if (this.testVO.examId) {
|
|
|
+ return "eval";
|
|
|
+ } else {
|
|
|
+ return "coder";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ state() {
|
|
|
+ if (this.type === "eval") {
|
|
|
+ if (new Date(this.testVO.endTime) < new Date()) {
|
|
|
+ return "FINISHED";
|
|
|
+ } else if (new Date(this.testVO.startTime) > new Date()) {
|
|
|
+ return "NOT_STARTED";
|
|
|
+ } else {
|
|
|
+ return "RUNNING";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (this.testVO.status === "CLOSED") {
|
|
|
+ return "CLOSED";
|
|
|
+ } else if (this.testVO.startAt * 1000 > new Date()) {
|
|
|
+ return "NOT_STARTED";
|
|
|
+ } else if (this.testVO.endAt * 1000 < new Date()) {
|
|
|
+ return "FINISHED";
|
|
|
+ } else {
|
|
|
+ return "RUNNING";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ async mounted() {
|
|
|
+ if (this.type === "eval") {
|
|
|
+ const res = await this.$apis.getUserAPI(this.testVO.creatorId);
|
|
|
+ this.teacher = res.data.data;
|
|
|
+ } else {
|
|
|
+ const res = await this.$apis.getUserAPI(this.testVO.creator.id);
|
|
|
+ if (res.data.code === 0) {
|
|
|
+ this.teacher = res.data.data;
|
|
|
+ } else {
|
|
|
+ this.teacher = { name: this.testVO.creator.username };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ timestampToTime(timestamp) {
|
|
|
+ const date = new Date(timestamp * 1000);
|
|
|
+ const Y = date.getFullYear() + "-";
|
|
|
+ const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
|
|
|
+ const D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
|
|
|
+ const h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
|
|
|
+ const m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes());
|
|
|
+ return Y + M + D + h + m;
|
|
|
+ },
|
|
|
+ toTestInfo() {
|
|
|
+ let messageBoxContent = "";
|
|
|
+ let messageBoxTitle = "";
|
|
|
+ let confirmButtonText = "";
|
|
|
+ let cancelButtonText = "让我想想";
|
|
|
+ let nextURL = "";
|
|
|
+
|
|
|
+ if (this.type === "eval") {
|
|
|
+ if (this.testVO.isJoined) {
|
|
|
+ messageBoxTitle = "Eval";
|
|
|
+ nextURL = "https://eval.seec.seecoder.cn?id_token=" + this.$store.state.user.token;
|
|
|
+ window.open(this.nextURL);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ // todo: eval系统暂时应该不存在参加了评测但是isJoined字段为false的情况。
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ messageBoxTitle = "Coder";
|
|
|
+ if (this.testVO.joined) {
|
|
|
+ nextURL = "https://coder.seec.seecoder.cn/exam/" + this.testVO.id + "?id_token=" + this.$store.state.user.token;
|
|
|
+ window.open(nextURL);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ messageBoxContent = "尚未参加该测试,是否立即参加?";
|
|
|
+ confirmButtonText = "立即参加";
|
|
|
+ nextURL = "https://coder.seec.seecoder.cn/exam?id_token=" + this.$store.state.user.token;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessageBox.confirm(messageBoxContent, messageBoxTitle, {
|
|
|
+ distinguishCancelAndClose: true,
|
|
|
+ confirmButtonText,
|
|
|
+ cancelButtonText,
|
|
|
+ }).then(() => {
|
|
|
+ if (nextURL.startsWith("http")) {
|
|
|
+ window.open(nextURL);
|
|
|
+ } else {
|
|
|
+ this.$router.push(nextURL);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.test {
|
|
|
+ min-height: 180px;
|
|
|
+ border-radius: 8px;
|
|
|
+ height: calc(100% - 14px);
|
|
|
+ position: relative;
|
|
|
+ border: 1px solid #cccccc;
|
|
|
+}
|
|
|
+
|
|
|
+.test:hover {
|
|
|
+ cursor: pointer;
|
|
|
+ border: 1px solid #aaaaaa;
|
|
|
+}
|
|
|
+
|
|
|
+.title {
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: medium;
|
|
|
+}
|
|
|
+
|
|
|
+.status {
|
|
|
+ text-align: right;
|
|
|
+}
|
|
|
+
|
|
|
+.course {
|
|
|
+ font-size: 10px;
|
|
|
+ margin-top: 4px;
|
|
|
+ color: #999999;
|
|
|
+}
|
|
|
+
|
|
|
+.teacher {
|
|
|
+ font-size: 10px;
|
|
|
+ margin-top: 10px;
|
|
|
+ color: #999999;
|
|
|
+}
|
|
|
+
|
|
|
+.time {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 10px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ color: #999999;
|
|
|
+}
|
|
|
+
|
|
|
+.comment {
|
|
|
+ background-color: #f6f6f6;
|
|
|
+ color: #777777;
|
|
|
+ margin-top: 10px;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 10px;
|
|
|
+ font-size: 10px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+</style>
|