Browse Source

发送消息

dusenyao 3 years ago
parent
commit
9ab5624b82

+ 15 - 0
src/api/course.js

@@ -557,3 +557,18 @@ export function GetMaterialInfo(data) {
     data
   });
 }
+
+/**
+ * 给课程学员发送消息
+ * @param {Object} data
+ */
+export function SendMessageToCourseStudent(data) {
+  let params = getRequestParams('message-message_manager-SendMessageToCourseStudent');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}

+ 1 - 1
src/icons/svg/arrival.svg

@@ -1 +1 @@
-<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.207 9.707a1 1 0 0 0-1.414-1.414L10.5 13.586l-2.293-2.293a1 1 0 0 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l6-6Z" fill="currentColor" /><path fill-rule="evenodd" clip-rule="evenodd" d="M3 2a1 1 0 0 0-1 1v18a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-6a1 1 0 0 0-.922.613c-.287.685-.615 1.119-.944 1.379-.315.248-.678.377-1.134.377-.456 0-.82-.129-1.134-.377-.329-.26-.657-.694-.944-1.379A1 1 0 0 0 9 2H3Zm1 18V4h4.368c.334.626.748 1.158 1.259 1.561A3.746 3.746 0 0 0 12 6.37c.882 0 1.687-.266 2.373-.808.511-.403.925-.935 1.259-1.561H20v16H4Z" fill="currentColor" /></svg>
+<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.207 9.707a1 1 0 0 0-1.414-1.414L10.5 13.586l-2.293-2.293a1 1 0 0 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l6-6Z" fill="currentColor"/><path fill-rule="evenodd" clip-rule="evenodd" d="M3 2a1 1 0 0 0-1 1v18a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-6a1 1 0 0 0-.922.613c-.287.685-.615 1.119-.944 1.379A1.752 1.752 0 0 1 12 4.369c-.456 0-.82-.129-1.134-.377-.329-.26-.657-.694-.944-1.379A1 1 0 0 0 9 2H3Zm1 18V4h4.368c.334.626.748 1.158 1.259 1.561A3.746 3.746 0 0 0 12 6.37c.882 0 1.687-.266 2.373-.808.511-.403.925-.935 1.259-1.561H20v16H4Z" fill="currentColor"/></svg>

+ 1 - 0
src/icons/svg/send-message.svg

@@ -0,0 +1 @@
+<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M24 0H0v24h24V0Z" fill="#fff" fill-opacity=".01"/><path d="M16.5 19H11v-4h7v-4h4v8h-2.5L18 20.5 16.5 19Z" stroke="#333" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M2 3h16v12H8.5l-2 2-2-2H2V3Z" stroke="#333" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.5 9h.5M13 9h.5M6 9h.5" stroke="#333" stroke-width="1.5" stroke-linecap="round"/></svg>

+ 0 - 1
src/icons/svg/task.svg

@@ -1 +0,0 @@
-<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.207 9.707a1 1 0 0 0-1.414-1.414L10.5 13.586l-2.293-2.293a1 1 0 0 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l6-6Z" fill="#3479FF"/><path fill-rule="evenodd" clip-rule="evenodd" d="M3 2a1 1 0 0 0-1 1v18a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-6a1 1 0 0 0-.922.613c-.287.685-.615 1.119-.944 1.379-.315.248-.678.377-1.134.377-.456 0-.82-.129-1.134-.377-.329-.26-.657-.694-.944-1.379A1 1 0 0 0 9 2H3Zm1 18V4h4.368c.334.626.748 1.158 1.259 1.561A3.746 3.746 0 0 0 12 6.37c.882 0 1.687-.266 2.373-.808.511-.403.925-.935 1.259-1.561H20v16H4Z" fill="#3479FF"/></svg>

+ 3 - 5
src/views/teacher/create_course/step_table/CreateTask.vue

@@ -68,14 +68,12 @@
             <el-input v-model="itemInfoBox.name" readonly />
           </div>
           <div class="item-info-date">
-            <div>时间</div>
+            <div>日期</div>
             <el-date-picker
               v-model="itemInfoBox.date"
               readonly
-              type="datetimerange"
+              type="daterange"
               range-separator="~"
-              value-format="yyyy-MM-dd HH:mm:ss"
-              unlink-panels
             />
           </div>
         </div>
@@ -457,7 +455,7 @@ export default {
       GetCSItemInfoBox({ id: this.curItemID }).then(
         ({ name, begin_time, end_time, pre_task_list, mid_task_list, after_task_list, learning_material_list }) => {
           this.itemInfoBox.name = name;
-          this.itemInfoBox.date = [begin_time, end_time];
+          this.itemInfoBox.date = [begin_time.split(' ')[0], end_time.split(' ')[0]];
           this.itemInfoBox.pre_task_list = pre_task_list;
           this.itemInfoBox.mid_task_list = mid_task_list;
           this.itemInfoBox.after_task_list = after_task_list;

+ 60 - 0
src/views/teacher/student_list/SendMessage.vue

@@ -0,0 +1,60 @@
+<template>
+  <el-dialog :visible="visible" :title="`发送消息给 ${titleName}`" :before-close="close">
+    <el-input
+      v-model="message"
+      resize="none"
+      type="textarea"
+      :rows="8"
+      placeholder="请输入内容"
+      maxlength="240"
+      show-word-limit
+    />
+
+    <div slot="footer">
+      <el-button type="primary" @click="send">
+        发送
+      </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  props: {
+    visible: {
+      default: false,
+      type: Boolean
+    },
+    titleName: {
+      default: '',
+      type: String
+    }
+  },
+  data() {
+    return {
+      message: ''
+    };
+  },
+  watch: {
+    visible(newVal) {
+      if (!newVal) return;
+      this.message = '';
+    }
+  },
+  methods: {
+    close() {
+      this.$emit('update:visible', false);
+    },
+
+    send() {
+      this.$emit('sendMessage', this.message);
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+@import '~@/styles/mixin';
+
+@include dialog;
+</style>

+ 92 - 25
src/views/teacher/student_list/index.vue

@@ -12,14 +12,18 @@
         <div class="tabs-left">
           <span
             v-for="item in tabList"
-            :key="item.id"
-            :class="['tabs-item', { active: item.id === activeID }]"
-            @click="changeTab(item.id)"
+            :key="item.type"
+            :class="['tabs-item', { active: item.type === curTab }]"
+            @click="changeTab(item.type)"
           >
             {{ item.name }}
           </span>
         </div>
-        <div />
+        <div v-if="curTab === tabList[1].type" class="tabs-right">
+          <el-button @click="sendMessage('all')">
+            <span><svg-icon icon-class="send-message" /> 群发消息</span>
+          </el-button>
+        </div>
       </div>
       <div class="student-table">
         <el-table :data="student_list">
@@ -43,10 +47,13 @@
           </el-table-column>
           <el-table-column fixed="right" width="120">
             <template slot-scope="{ row }">
-              <template v-if="activeID === 'new'">
+              <template v-if="curTab === tabList[0].type">
                 <span class="agree" @click="auditCourseStudent(row.course_student_id, 'true')"> 同意 </span>
                 <span class="refuse" @click="auditCourseStudent(row.course_student_id, 'false')"> 拒绝 </span>
               </template>
+              <template v-if="curTab === tabList[1].type">
+                <span class="agree" @click="sendMessage('single', row.student_id, row.student_name)">发消息</span>
+              </template>
             </template>
           </el-table-column>
         </el-table>
@@ -64,30 +71,40 @@
       @current-change="changePage"
       @size-change="changePageSize"
     />
+
+    <send-message :visible.sync="visible" :title-name="titleName" @sendMessage="sendMessageToCourseStudent" />
   </div>
 </template>
 
 <script>
 import { PageQueryCourseStudentList } from '@/api/list';
-import { AuditCourseStudent } from '@/api/course';
+import { AuditCourseStudent, SendMessageToCourseStudent } from '@/api/course';
+import SendMessage from './SendMessage.vue';
 
 export default {
+  components: {
+    SendMessage
+  },
   data() {
     return {
       course_id: this.$route.params.id,
       student_name: '',
-      activeID: 'new',
+      curTab: 'new',
+      visible: false,
+      titleName: '',
+      type: '',
+      student_id: '',
       student_list: [],
       page_capacity: 10,
       cur_page: 1,
       total_count: 0,
       tabList: [
         {
-          id: 'new',
+          type: 'new',
           name: '新申请'
         },
         {
-          id: 'list',
+          type: 'list',
           name: '学生列表'
         }
       ]
@@ -98,38 +115,60 @@ export default {
   },
   methods: {
     queryCourseStudentList() {
-      let data = {
+      PageQueryCourseStudentList({
         student_name: this.student_name,
         course_id: this.course_id,
         page_capacity: this.page_capacity,
-        cur_page: this.cur_page
-      };
-
-      if (this.activeID === 'new') {
-        data['audit_status_list'] = [0];
-      } else {
-        data['audit_status_list'] = [1];
-      }
-
-      PageQueryCourseStudentList(data).then(({ student_list, total_count, cur_page }) => {
+        cur_page: this.cur_page,
+        audit_status_list: this.curTab === 'new' ? [0] : [1]
+      }).then(({ student_list, total_count, cur_page }) => {
         this.student_list = student_list;
         this.total_count = total_count;
         this.cur_page = cur_page;
       });
     },
-    changeTab(id) {
+
+    changeTab(tab) {
       this.student_list = [];
-      this.activeID = id;
+      this.curTab = tab;
       this.queryCourseStudentList();
     },
+
     changePage(newPage) {
       this.cur_page = newPage;
       this.queryCourseStudentList();
     },
+
     changePageSize(pageSize) {
       this.page_capacity = pageSize;
       this.queryCourseStudentList();
     },
+
+    sendMessage(type, student_id, student_name) {
+      this.type = type;
+      this.student_id = student_id;
+      if (type === 'all') {
+        this.titleName = '全部';
+      } else {
+        this.titleName = student_name;
+      }
+      this.visible = true;
+    },
+
+    sendMessageToCourseStudent(content) {
+      let loading = this.$loading('发送消息中...');
+      SendMessageToCourseStudent({
+        course_id: this.course_id,
+        content,
+        type: this.type,
+        student_id: this.student_id
+      }).then(({ message_count }) => {
+        loading.close();
+        this.visible = false;
+        this.$message.success(`已成功发送${message_count}条消息`);
+      });
+    },
+
     auditCourseStudent(course_student_id, is_audited) {
       AuditCourseStudent({ course_student_id, is_audited }).then(() => {
         this.$message.success('审核课程学员成功!');
@@ -140,7 +179,7 @@ export default {
 };
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 @import '~@/styles/mixin';
 
 .student-list {
@@ -154,7 +193,6 @@ export default {
   &-container {
     width: 100%;
     min-height: calc(100vh - 240px);
-    padding: 24px 32px;
     margin-top: 16px;
     background-color: #fff;
     border-radius: 8px;
@@ -162,10 +200,14 @@ export default {
     // 标签
     .tabs {
       display: flex;
+      justify-content: space-between;
+      height: 68px;
+      padding: 16px 16px 0 32px;
       border-bottom: 1px solid #d9d9d9;
 
       &-left {
         display: flex;
+        align-items: flex-end;
 
         .tabs-item {
           padding-bottom: 16px;
@@ -174,7 +216,7 @@ export default {
 
           &.active {
             font-weight: 600;
-            border-bottom: 2px solid $basic-color;
+            box-shadow: 0 1px 0 $basic-color, 0 -1px 0 $basic-color inset;
           }
 
           &:not(:first-child) {
@@ -182,6 +224,20 @@ export default {
           }
         }
       }
+
+      &-right {
+        .el-button {
+          height: 40px;
+          padding: 8px 16px;
+
+          .svg-icon {
+            width: 24px;
+            height: 24px;
+            margin-right: 8px;
+            vertical-align: middle;
+          }
+        }
+      }
     }
 
     // 学员列表
@@ -207,6 +263,7 @@ export default {
       }
 
       .el-avatar {
+        margin-left: 22px;
         vertical-align: sub;
       }
 
@@ -219,3 +276,13 @@ export default {
   }
 }
 </style>
+
+<style lang="scss">
+.student-list {
+  .student-table {
+    .el-table__header {
+      display: none;
+    }
+  }
+}
+</style>