|
|
@@ -0,0 +1,299 @@
|
|
|
+<template>
|
|
|
+ <el-card class="project" shadow="hover" @click="toProjectInfo">
|
|
|
+
|
|
|
+ <div :style="{borderBottom: type==='courseProject' ? '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==='courseProject'" style="padding: 0 4px 0 4px; position: absolute; right: 0; bottom: -30px; color: white">
|
|
|
+ D
|
|
|
+ </div>
|
|
|
+ <div v-else style="padding: 0 3px 0 3px; position: absolute; right: 0; bottom: -30px; color: white">
|
|
|
+ P
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="16">
|
|
|
+ <el-col class="title">
|
|
|
+ {{ title }}
|
|
|
+ </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_IN' && !isPublicTest" size="small" type="success">已参加</el-tag>
|
|
|
+ <el-tag v-else-if="state==='RUNNING_NOT' && !isPublicTest" size="small">未参加</el-tag>
|
|
|
+ <el-tag v-else-if="isPublicTest" 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 class="course" v-if="course!==''">
|
|
|
+ {{ course }}
|
|
|
+ </el-row>
|
|
|
+ <el-row class="teacher">
|
|
|
+ {{ teacherName }}
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row class="time">
|
|
|
+ {{ timePeriod }}
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row v-if="type==='courseProject'" class="comment">
|
|
|
+ {{ projectVO.comment }}
|
|
|
+ </el-row>
|
|
|
+ </el-card>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import {ElMessage, ElMessageBox} from "element-plus";
|
|
|
+import store from "@/store";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "ProjectCard",
|
|
|
+ props: {
|
|
|
+ projectVO: Object,
|
|
|
+ isPublicTest: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ teacher: Object,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ isLogin() {
|
|
|
+ return store.state.user.token;
|
|
|
+ },
|
|
|
+ isCreator() {
|
|
|
+ if (this.projectVO.projectId) {
|
|
|
+ return Number(this.projectVO.course.teacherId) === Number(this.$store.state.user.id);
|
|
|
+ }else{
|
|
|
+ return this.projectVO.creator.username === this.$store.state.user.phone;
|
|
|
+ }
|
|
|
+ // todo
|
|
|
+ },
|
|
|
+ isTeacher() {
|
|
|
+ return this.$store.getters.isTeacher;
|
|
|
+ },
|
|
|
+ isStudent() {
|
|
|
+ return this.$store.getters.isStudent;
|
|
|
+ },
|
|
|
+ type() {
|
|
|
+ if (this.projectVO.projectId) {
|
|
|
+ return "courseProject";
|
|
|
+ } else {
|
|
|
+ return "commonProject";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ title() {
|
|
|
+ return this.projectVO.name;
|
|
|
+ },
|
|
|
+ course() {
|
|
|
+ if (this.type === "courseProject") {
|
|
|
+ return "所属课程: " + this.projectVO.course;
|
|
|
+ } else {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ teacherName() {
|
|
|
+ if (this.type === "courseProject") {
|
|
|
+ return "教师: " + this.teacher.name;
|
|
|
+ // todo
|
|
|
+ } else {
|
|
|
+ return "教师: " + this.teacher;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ timePeriod() {
|
|
|
+ return "时间: " + this.projectVO.startTime.substring(0, 16) + "至" + this.projectVO.endTime.substring(0, 16);
|
|
|
+ },
|
|
|
+ state() {
|
|
|
+ const now = new Date();
|
|
|
+ if (this.type === "courseProject") {
|
|
|
+ if (new Date(this.projectVO.endTime) < now) {
|
|
|
+ return "FINISHED";
|
|
|
+ } else if (new Date(this.projectVO.startTime) > now) {
|
|
|
+ return "NOT_STARTED";
|
|
|
+ } else if (this.projectVO.isJoined) {
|
|
|
+ return "RUNNING_IN";
|
|
|
+ } else {
|
|
|
+ return "RUNNING_NOT";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (this.projectVO.status === "CLOSED") {
|
|
|
+ return "CLOSED";
|
|
|
+ } else if (this.projectVO.startAt * 1000 > now) {
|
|
|
+ return "NOT_STARTED";
|
|
|
+ } else if (this.projectVO.endAt * 1000 < now) {
|
|
|
+ return "FINISHED";
|
|
|
+ } else if (this.projectVO.joined) {
|
|
|
+ return "RUNNING_IN";
|
|
|
+ } else {
|
|
|
+ return "RUNNING_NOT";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ async created() {
|
|
|
+ // if (this.type === "courseProject") {
|
|
|
+ // this.teacher = (await this.$apis.getUserAPI(this.projectVO.course["teacherId"])).data.data;
|
|
|
+ // } else {
|
|
|
+ // this.teacher = (await this.$apis.getNameByUsernameAPI(this.projectVO.creator.username)).data.data;
|
|
|
+ // }
|
|
|
+ // todo
|
|
|
+ },
|
|
|
+ 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;
|
|
|
+ },
|
|
|
+ async toProjectInfo() {
|
|
|
+ if (!this.isLogin) {
|
|
|
+ ElMessage({
|
|
|
+ showClose: true,
|
|
|
+ message: "请先登录",
|
|
|
+ type: "warning",
|
|
|
+ duration: 1000,
|
|
|
+ });
|
|
|
+ await this.$router.push({name: "Auth", params: {login_to: "/portal"}});
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.isCreator) {
|
|
|
+ // todo
|
|
|
+ } else if (this.isTeacher) {
|
|
|
+ this.$message.error("无权访问其他教师创建的项目");
|
|
|
+ } else {
|
|
|
+ let messageBoxContent = "";
|
|
|
+ let messageBoxTitle = "";
|
|
|
+ let confirmButtonText = "";
|
|
|
+ let cancelButtonText = "让我想想";
|
|
|
+ let nextURL = "";
|
|
|
+ if (this.type === "courseProject") {
|
|
|
+ messageBoxTitle = "courseProject";
|
|
|
+ if (this.projectVO.isJoined) {
|
|
|
+ // nextURL = "https://eval.seec.seecoder.cn/exam/" + this.projectVO.id + "/before-exam/?id_token=" + this.$store.state.user.token;
|
|
|
+ // window.open(nextURL);
|
|
|
+ // todo 项目详情页跳转到哪
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ const projectId = (await this.$apis.getCourseByEvalId(this.projectVO.course.id)).data.data;
|
|
|
+ // todo API
|
|
|
+ if (projectId) {
|
|
|
+ const isProjectSelected = (await this.$apis.checkCourseSelection(courseId, this.$store.state.user.id)).data.data;
|
|
|
+ // todo API
|
|
|
+ if (isProjectSelected) {
|
|
|
+ messageBoxContent = "是否立即查看项目详情";
|
|
|
+ confirmButtonText = "立即查看";
|
|
|
+ // nextURL = "https://eval.seec.seecoder.cn/student/home/?id_token=" + this.$store.state.user.token;
|
|
|
+ } else {
|
|
|
+ messageBoxContent = "尚未加入项目,是否立即加入?";
|
|
|
+ confirmButtonText = "立即加入";
|
|
|
+ nextURL = "/course/" + courseId;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ messageBoxContent = "是否立即查看项目详情";
|
|
|
+ confirmButtonText = "立即查看";
|
|
|
+ // nextURL = "https://eval.seec.seecoder.cn/student/home/?id_token=" + this.$store.state.user.token;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ messageBoxTitle = "CommonProject";
|
|
|
+ if (this.projectVO.joined) {
|
|
|
+ // nextURL = "https://coder.seec.seecoder.cn/exam/" + this.projectVO.id + "?id_token=" + this.$store.state.user.token;
|
|
|
+ // window.open(nextURL);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ const projectId = (await this.$apis.getCourseByCoderId(this.projectVO.courseId)).data.data;
|
|
|
+ if (projectId) {
|
|
|
+ const isProjectSelected = (await this.$apis.checkCourseSelection(courseId, this.$store.state.user.id)).data.data;
|
|
|
+ if (isProjectSelected) {
|
|
|
+ messageBoxContent = "是否立即查看项目详情";
|
|
|
+ confirmButtonText = "立即查看";
|
|
|
+ // nextURL = "https://coder.seec.seecoder.cn/exam?id_token=" + this.$store.state.user.token;
|
|
|
+ } else {
|
|
|
+ messageBoxContent = "尚未加入项目,是否立即加入?";
|
|
|
+ confirmButtonText = "立即加入";
|
|
|
+ nextURL = "/project/" + projectId;
|
|
|
+ }
|
|
|
+ } 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>
|
|
|
+.project {
|
|
|
+ min-height: 180px;
|
|
|
+ border-radius: 8px;
|
|
|
+ height: calc(100% - 14px);
|
|
|
+ position: relative;
|
|
|
+ border: 1px solid #cccccc;
|
|
|
+}
|
|
|
+
|
|
|
+.project: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>
|