Explorar o código

hyl添加了课件类、上传下载课件

chillqi %!s(int64=3) %!d(string=hai) anos
pai
achega
8dc2f9a697

+ 7 - 0
src/api/group.js

@@ -13,6 +13,10 @@ function addGroupMember(data){
     return axios.post(`${prefix}/member/add`,data);
 }
 
+function sendInvitation(data){
+    return axios.post(`${prefix}/invite`,data);
+}
+
 function findGroup(courseId){
     return axios.get(`${prefix}`,{
         params :{
@@ -37,10 +41,13 @@ function findGroupRule(courseId){
     });
 }
 
+
+
 const groupAPIs={
     createGroupRule,
     createGroup,
     addGroupMember,
+    sendInvitation,
     findGroup,
     findAllGroupsByCourse,
     findGroupRule,

+ 5 - 0
src/api/message.js

@@ -34,6 +34,10 @@ function readMessage(id) {
   return axios.put(`${prefix}/read`, {id});
 }
 
+function getUnreadInvitations(){
+  return axios.put(`${prefix}/getInvitations`);
+}
+
 const messageAPIs = {
   getUnreadMessages,
   createMessage,
@@ -42,6 +46,7 @@ const messageAPIs = {
   deleteMessage,
   getViewByMessage,
   readMessage,
+  getUnreadInvitations
 };
 
 export default messageAPIs;

+ 8 - 2
src/components/GlobalHeader.vue

@@ -10,7 +10,7 @@
         任务
       </el-menu-item>
       <el-menu-item index="3">
-        课程广场
+        课程
       </el-menu-item>
       <el-menu-item index="4">
         项目广场
@@ -120,8 +120,14 @@ export default {
     unReadAnnouncements() {
       return this.$store.getters.unReadAnnouncements;
     },
+    unReadInvitations(){
+      return this.$store.getters.unReadInvitations;
+    },
     unreadNum() {
-      return this.unReadAnnouncements.length + this.unReadMessages.length > 99 ? "99+" : this.unReadAnnouncements.length + this.unReadMessages.length + "";
+      const x = this.unReadAnnouncements === undefined ? 0 : this.unReadAnnouncements.length;
+      const y = this.unReadMessages === undefined ? 0 : this.unReadMessages.length;
+      const z = this.unReadInvitations === undefined ? 0 : this.unReadInvitations.length;
+      return x + y + z> 99 ? "99+" : x + y + z + "";
     },
   },
 

+ 1 - 1
src/components/TestCard.vue

@@ -69,7 +69,7 @@ export default {
       if (this.testVO.examId) {
         return Number(this.testVO.course.teacherId) === Number(this.$store.state.user.id);
       }else{
-        return this.testVO.creator.username === this.$store.state.user.phone;
+        return this.testVO.creator.username === this.$store.state.user.username;
       }
     },
     isTeacher() {

+ 10 - 2
src/store/modules/message.js

@@ -3,6 +3,7 @@ const messages = {
     return {
       messages: [],
       announcements: [],
+      invitations:[]
     };
   },
 
@@ -12,13 +13,17 @@ const messages = {
     },
     set_announcements(state, data) {
       state.announcements = data;
+    },
+    set_invitations(state,data){
+      state.invitations = data;
     }
   },
 
   actions: {
     async fetchMessages({commit, state}, that) {
-      commit("set_messages", (await that.$apis.getUnreadAnnouncements()).data.data);
-      commit("set_announcements", (await that.$apis.getUnreadMessages()).data.data);
+      commit("set_messages", (await that.$apis.getUnreadMessages()).data.data);
+      commit("set_announcements", (await that.$apis.getUnreadAnnouncements()).data.data);
+      commit("set_invitations",(await that.$apis.getUnreadInvitations()).data.data);
     }
   },
 
@@ -29,6 +34,9 @@ const messages = {
     unReadAnnouncements(state) {
       return state.announcements;
     },
+    unReadInvitations(state) {
+      return state.invitations;
+    }
   },
 };
 

+ 186 - 0
src/views/CoursePage/tabs/GroupTab.vue

@@ -86,11 +86,38 @@
 <script>
   import {ElMessage, ElMessageBox} from "element-plus";
 
+<<<<<<< HEAD
   export default {
     name: "GroupTab",
     props: {
       courseId: {
         required: true,
+=======
+export default {
+  name: "GroupTab",
+  props: {
+    courseId: {
+      required: true,
+    },
+    teacherId: {
+      required: true,
+    },
+  },
+  data() {
+    return {
+      groupTableData: [],
+      groupData: null,
+
+      isRuleExisted: false,
+      ruleFormDialog: false,
+      maxNameLen:10,
+      ruleForm: {
+        dialogTitle: "制定组队规则",
+        courseVO: null,
+        id: null,
+        maxSize: null,
+        maxNameLen: null,
+>>>>>>> efe3831aac9edd6d113ed30d273ebeb3776bb381
       },
       teacherId: {
         required: true,
@@ -111,6 +138,7 @@
           maxSize: null,
           maxNameLen: null,
         },
+<<<<<<< HEAD
         ruleFormRule: {
           maxSize: {
             required: true, message: "请选择小组最大成员人数", trigger: "change",
@@ -132,6 +160,158 @@
                 } else {
                   return Number(value);
                 }
+=======
+        maxNameLen: {
+          required: true, message: "请选择组名最大长度", trigger: "change",
+        }
+      },
+      addMemberRule: {
+        phone: [{required: true, message: "手机号不能为空"},
+          {
+            type: "number",
+            message: "手机号格式不正确",
+            trigger: "blur",
+            transform(value) {
+              var phonereg = 11 && /^((13|14|15|16|17|18|19)[0-9]{1}\d{8})$/;
+              if (!phonereg.test(value)) {
+                return false;
+              } else {
+                return Number(value);
+              }
+            }
+          }],
+      },
+
+      createGroupDialog: false,
+      createGroupForm: {
+        dialogTitle: "队伍信息",
+        courseId: null,
+        name: null,
+      },
+
+      addMemberDialog: false,
+      addMemberForm: {
+        dialogTitle: "组员信息",
+        phone: null,
+      },
+    };
+  },
+  computed: {
+    isCreator() {
+      return Number(this.teacherId) === Number(this.$store.state.user.id);
+    },
+  },
+  mounted() {
+    this.init();
+  },
+  methods: {
+    async init() {
+      const _this = this;
+      const ruleRes = (await _this.$apis.findGroupRule(_this.courseId)).data;
+      _this.isRuleExisted = !ruleRes.code;
+      if (_this.isRuleExisted) {
+        _this.maxNameLen=ruleRes.data.maxNameLen;
+        const groupsRes = (await _this.$apis.findAllGroupsByCourse(_this.courseId)).data;
+        if (!groupsRes.code) {
+          _this.groupTableData = groupsRes.data;
+        }
+        const groupRes = (await _this.$apis.findGroup(_this.courseId)).data;
+        if (!groupRes.code) {
+          _this.groupData = groupRes.data;
+        }
+      }
+    },
+
+    beforeRuleFormClose() {
+      const _this = this;
+      _this.ruleFormDialog = false;
+      _this.$refs.ruleFormRef.resetFields();
+    },
+
+    handleCreateRuleConfirm() {
+      this.$refs.ruleFormRef.validate((valid) => {
+        if (valid) {
+          let RuleVO = {
+            courseVO: {id: this.courseId},
+            maxSize: this.ruleForm.maxSize,
+            maxNameLen: this.ruleForm.maxNameLen,
+          };
+          this.$apis.createGroupRule(RuleVO)
+            .then(res => {
+              if (res.data.code) {
+                ElMessage.error(res.data.message);
+              } else {
+                this.isRuleExisted = true;
+                this.ruleFormDialog = false;
+                this.$refs.ruleFormRef.resetFields();
+                ElMessage.success("创建规则成功");
+              }
+            });
+        }
+      });
+    },
+
+    beforeGroupFormClose() {
+      this.createGroupDialog = false;
+      this.$refs.createGroupFormRef.resetFields();
+    },
+
+    handleCreateGroupConfirm() {
+      if (this.createGroupForm.name.length===0){
+        return ;
+      }
+      if (this.createGroupForm.name.length>this.maxNameLen){
+        this.createGroupForm.name="";
+        ElMessage.error("创建队伍失败!队伍名称长度不能超过"+this.maxNameLen+"!");
+      }
+      this.$refs.createGroupFormRef.validate((valid) => {
+        if (valid) {
+          let GroupVO = {
+            courseId: this.courseId,
+            name: this.createGroupForm.name,
+          };
+          this.$apis.createGroup(GroupVO)
+            .then(res => {
+              if (res.data.code) {
+                ElMessage.error(res.data.message);
+              } else {
+                this.groupData = res.data.data;
+                this.groupTableData.push(res.data.data);
+                this.createGroupDialog = false;
+                this.$refs.createGroupFormRef.resetFields();
+                ElMessage.success("创建队伍成功");
+              }
+            });
+        }
+      });
+    },
+
+    beforeGroupMemberFormClose() {
+      this.addMemberDialog = false;
+      this.$refs.addMemberFormRef.resetFields();
+    },
+
+    handleAddMemberConfirm() {
+      const _this = this;
+      this.$refs.addMemberFormRef.validate(async (valid) => {
+        if (valid) {
+          const userIdRes = (await _this.$apis.findUserIdByPhone(_this.addMemberForm.phone)).data;
+          if (userIdRes.code) {
+            ElMessage.error(userIdRes.message);
+            return;
+          }
+          let groupMemberVO = {
+            userId: userIdRes.data,
+            groupId: _this.groupData["groupVO"].id,
+            courseId: _this.courseId,
+          };
+          this.$apis.sendInvitation(groupMemberVO)
+            .then(res => {
+              if (res.data.code) {
+                ElMessage.error(res.data.message);
+              } else {
+                ElMessage.success("已发送邀请,请等候其同意。");
+>>>>>>> efe3831aac9edd6d113ed30d273ebeb3776bb381
               }
             }],
         },
@@ -273,7 +453,13 @@
       },
 
     },
+<<<<<<< HEAD
   };
+=======
+
+  },
+};
+>>>>>>> efe3831aac9edd6d113ed30d273ebeb3776bb381
 </script>
 
 <style scoped>

+ 29 - 0
src/views/ManagePage/ManagePage.vue

@@ -2,6 +2,7 @@
   <el-row id="manage-page-body">
     <el-col :span="3">
       <el-card style="position: fixed;">
+<<<<<<< HEAD
         <el-menu default-active="1" @select="handleSelect">
           <el-menu-item index="0">
             <el-icon>
@@ -28,6 +29,34 @@
             <span style="padding-left: 20px">全部题目</span>
           </el-menu-item>
         </el-menu>
+=======
+      <el-menu default-active="1" @select="handleSelect">
+        <el-menu-item index="0">
+          <el-icon>
+            <Back/>
+          </el-icon>
+          <span style="padding-left: 20px">返回首页</span>
+        </el-menu-item>
+        <el-menu-item index="1">
+          <el-icon>
+            <Document/>
+          </el-icon>
+          <span style="padding-left: 20px">全部课程</span>
+        </el-menu-item>
+        <el-menu-item index="2">
+          <el-icon>
+            <DocumentChecked/>
+          </el-icon>
+          <span style="padding-left: 20px">全部测试</span>
+        </el-menu-item>
+        <el-menu-item index="3">
+          <el-icon>
+            <DocumentChecked/>
+          </el-icon>
+          <span style="padding-left: 20px">全部题目</span>
+        </el-menu-item>
+      </el-menu>
+>>>>>>> efe3831aac9edd6d113ed30d273ebeb3776bb381
       </el-card>
     </el-col>
     <el-col :span="1"/>

+ 2 - 2
src/views/ManagePage/managePage.css

@@ -1,6 +1,6 @@
 #manage-page-body {
-    margin: 40px 60px 80px 60px;
-    min-height: calc(100vh - 840px);
+    margin: 40px 160px 80px 0;
+    min-height: calc(100vh - 160px);
 }
 
 .card-header {

+ 29 - 1
src/views/MessagePage/MessagePage.vue

@@ -21,6 +21,12 @@
             </el-icon>
             <span style="padding-left: 20px">消息列表</span>
           </el-menu-item>
+          <el-menu-item index="3">
+            <el-icon>
+              <Link/>
+            </el-icon>
+            <span style="padding-left: 20px">邀请列表</span>
+          </el-menu-item>
         </el-menu>
       </el-card>
     </el-col>
@@ -53,6 +59,15 @@
           </el-icon>
           <div class="tip">暂无新消息~</div>
         </div>
+        <div v-else-if="activeIndex==='3' && myUnReadInvitation.length !== 0" class="message-page-main">
+          <MessageCard v-for="i in myUnReadInvitation" :key="i.id" :messageVO="i" @refresh="refresh()"/>
+        </div>
+        <div v-else-if="activeIndex==='3' && myUnReadInvitation.length === 0" style="margin: 100px 0 0 calc(50% - 36px); min-height: 300px">
+          <el-icon :size="72" color="#bfbfbf">
+            <ChatSquare/>
+          </el-icon>
+          <div class="tip">暂无新邀请~</div>
+        </div>
       </el-card>
     </el-col>
   </el-row>
@@ -70,17 +85,26 @@ export default {
       activeIndex: "1",
       myUnReadAnnouncement: [],
       myUnReadMessage: [],
+      myUnReadInvitation:[],
       messageDayPeriod: 0,
     };
   },
   computed: {
     title() {
-      return this.activeIndex === "1" ? "通知列表" : "消息列表";
+      if (this.activeIndex==="1"){
+        return "通知列表";
+      }else if (this.activeIndex==="2"){
+        return "消息列表";
+      }else if (this.activeIndex==="3"){
+        return "邀请列表";
+      }
+      return "";
     },
   },
   async created() {
     this.myUnReadAnnouncement = (await this.$apis.getUnreadAnnouncements()).data.data;
     this.myUnReadMessage = (await this.$apis.getUnreadMessages(this.messageDayPeriod)).data.data;
+    this.myUnReadInvitation = (await this.$apis.getUnreadInvitations()).data.data;
   },
   methods: {
     handleSelect(index) {
@@ -93,6 +117,10 @@ export default {
       this.messageDayPeriod += 1;
       this.myUnReadMessage = (await this.$apis.getUnreadMessages(this.messageDayPeriod)).data.data;
     },
+    async refresh(){
+      this.myUnReadInvitation = (await this.$apis.getUnreadInvitations()).data.data;
+      this.$store.dispatch("fetchMessages", this);
+    }
   },
 };
 </script>

+ 41 - 3
src/views/MessagePage/components/MessageCard.vue

@@ -7,6 +7,7 @@
         <el-tag size="large" type="warning" v-else-if="type === 'EXAM'" class="tag">考试</el-tag>
         <el-tag size="large" type="" v-else-if="type === 'COMMENT'" class="tag">回复</el-tag>
         <el-tag size="large" type="warning" v-else-if="type === 'COURSE'" class="tag">评论</el-tag>
+        <el-tag size="large" type="" v-if="type === 'INVITATION'" class="tag">邀请</el-tag>
       </el-row>
       <el-row class="time">
         {{ time }}
@@ -30,18 +31,23 @@
     </el-col>
     <el-col :span="2"/>
     <el-col :span="2" style="display: flex; flex-direction:column; justify-content: center">
-      <div>
+      <div v-if="type !== 'INVITATION'">
         <span>详情</span>
         <el-icon :size="20" style="position: relative; top: 5px">
           <ArrowRightBold/>
         </el-icon>
       </div>
+      <div v-if="type === 'INVITATION'">
+        <el-button style="position: absolute; right: 130px; top: 15px" @click="accept">接受</el-button>
+        <el-button style="position: absolute; right: 50px; top:15px" @click="refuse">拒绝</el-button>
+      </div>
     </el-col>
   </el-row>
 </template>
 
 <script>
 import {ArrowRightBold} from "@element-plus/icons-vue";
+import {ElMessage} from "element-plus";
 
 export default {
   name: "MessageCard",
@@ -79,20 +85,52 @@ export default {
   },
 
   async created() {
-    if (this.messageVO.courseId) {
-      this.course = (await this.$apis.getCourseById(this.messageVO.courseId)).data.data["name"];
+    //对于INVITATION来说,课程id被放置在了targetId域中
+    //对于ANNOUNCEMENT来说,课程id被放置在了courseId中
+    //对于COMMENT来说,没有courseId
+    if (this.type==="INVITATION"){
+      this.course = (await this.$apis.getCourseById(this.messageVO.targetId)).data.data["name"];
+    }else {
+      if (this.messageVO.courseId) {
+        this.course = (await this.$apis.getCourseById(this.messageVO.courseId)).data.data["name"];
+      }
     }
   },
 
   methods: {
     async jump() {
+      if (this.messageVO.type==="INVITATION" || this.messageVO.actionType==="INVITATION"){
+        return;
+      }
       if (this.messageVO.courseId) {
+        await this.$apis.readAnnouncement(this.messageVO.id);
         await this.$router.push({ name: "CourseDetail", params: { jump_from_message: "1", id: this.messageVO.courseId } });
       } else {
         const viewInfo = (await this.$apis.getViewByMessage(this.messageVO.id)).data.data;
         await this.$apis.readMessage(this.messageVO.id);
         await this.$router.push({ name: "CourseDetail", params: { jump_from_message: "2", id: viewInfo["course"] } });
       }
+    },
+    async accept(){
+      //由于后端数据库存不了组号,只能将发起者用户id当做组号传到后端,让后端来解析组号
+      let groupMemberVO = {
+        userId: this.messageVO.mntId,
+        groupId: this.messageVO.sender.id,
+        courseId: this.messageVO.targetId
+      };
+      this.$apis.addGroupMember(groupMemberVO).then(res=>{
+        if (res.data.code) {
+          ElMessage.error(res.data.message);
+        } else {
+          ElMessage.success("添加小组成功!");
+        }
+      });
+      await this.$apis.readMessage(this.messageVO.id);
+      this.$emit("refresh");
+    },
+    async refuse(){
+      await this.$apis.readMessage(this.messageVO.id);
+      this.$emit("refresh");
     }
   }
 };

+ 19 - 2
src/views/PortalPage/components/CarouselCard.vue

@@ -1,12 +1,13 @@
 <template>
   <el-carousel id="carousel-card-body" :interval="4000" height="180px" type="card">
-    <el-carousel-item v-for="item in contents" :key="item">
-      <img :src=item alt="err" style="object-fit: cover;object-position:top;height: 180px; width: 600px">
+    <el-carousel-item v-for="(item,index) in contents" :key="item">
+      <img :src=item alt="err" style="object-fit: cover;object-position:top;height: 180px; width: 600px" @click="jump(index)">
     </el-carousel-item>
   </el-carousel>
 </template>
 
 <script>
+
 export default {
   name: "CarouselCard",
   data() {
@@ -16,7 +17,23 @@ export default {
         require("@/assets/carousel-SE2.png"),
         require("@/assets/seec-banner.png"),
       ],
+      link:[]
     };
+  },
+  async created() {
+    const exampleClasses = (await this.$apis.getExampleCourses()).data.data;
+    for (let i=0; i<Math.min(exampleClasses.length,3); i++){
+      this.contents[i]=exampleClasses[i].imageUrl;
+      this.link[i]=exampleClasses[i].id;
+    }
+    this.$forceUpdate();
+  },
+  methods:{
+    jump(k){
+      if (this.link.length>k){
+        this.$router.push({ name: "CourseDetail", params: {id:this.link[k] } });
+      }
+    }
   }
 };
 </script>

+ 4 - 4
src/views/TestPage/TestPage.vue

@@ -34,7 +34,7 @@
         </template>
         <div v-if="this.activeIndex === '1'">
           <el-tabs v-model="activeTestPaneName" style="width: 100%">
-            <el-tab-pane label="评测题" name="eval">
+            <el-tab-pane label="eval测试" name="eval">
               <div v-for="(item, key) in evalExamList" :key="key">
                 <div v-if="item.length !== 0">
                   <div>
@@ -46,7 +46,7 @@
                 </div>
               </div>
             </el-tab-pane>
-            <el-tab-pane label="代码题" name="coder">
+            <el-tab-pane label="coder测试" name="coder">
               <div v-for="(item, key) in coderExamList" :key="key">
                 <div v-if="item.length !== 0">
                   <div>
@@ -63,7 +63,7 @@
 
         <div v-if="this.activeIndex === '2' && isStudent">
           <el-tabs v-model="activeTestPaneName_my" style="width: 100%">
-            <el-tab-pane label="评测题" name="eval">
+            <el-tab-pane label="eval测试" name="eval">
               <div v-for="(item, key) in evalExamList_my" :key="key">
                 <div>
                   <el-divider style="margin: 10px 0 20px 0" content-position="left">{{ key }}</el-divider>
@@ -73,7 +73,7 @@
                 </div>
               </div>
             </el-tab-pane>
-            <el-tab-pane label="代码题" name="coder">
+            <el-tab-pane label="coder测试" name="coder">
               <div v-for="(item, key) in coderExamList_my" :key="key">
                 <div>
                   <el-divider style="margin: 10px 0 20px 0" content-position="left">{{ key }}</el-divider>