Bläddra i källkod

新的任务列表
将与任务列表相关的页面改为 setup 格式

dusenyao 2 år sedan
förälder
incheckning
e6b521b0e3

+ 1 - 1
.npmrc

@@ -1 +1 @@
-engine-strict = true
+engine-strict = false

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 22262 - 1
package-lock.json


+ 7 - 7
package.json

@@ -18,7 +18,7 @@
     "awe-dnd": "^0.3.4",
     "axios": "^0.27.2",
     "book-ui": "file:../book-ui-0.3.15.tgz",
-    "core-js": "^3.25.5",
+    "core-js": "^3.26.0",
     "dayjs": "^1.11.6",
     "element-ui": "^2.15.10",
     "gcls-book-question-ui": "file:../gcls-book-question-ui-0.1.0.tgz",
@@ -31,7 +31,7 @@
     "nprogress": "^0.2.0",
     "tinymce": "^5.10.5",
     "vue": "^2.7.13",
-    "vue-i18n": "^8.27.2",
+    "vue-i18n": "^8.28.2",
     "vue-pdf": "^4.3.0",
     "vue-router": "^3.6.5",
     "vue-video-player": "^5.0.2",
@@ -49,25 +49,25 @@
     "@vue/cli-service": "~5.0.8",
     "@vue/eslint-config-prettier": "^7.0.0",
     "@vue/preload-webpack-plugin": "^2.0.0",
-    "@vue/test-utils": "^1.3.0",
+    "@vue/test-utils": "^1.3.2",
     "babel-jest": "^27.5.1",
     "babel-plugin-dynamic-import-node": "^2.3.3",
     "compression-webpack-plugin": "^6.1.1",
     "eslint": "^7.32.0",
     "eslint-plugin-prettier": "^4.2.1",
-    "eslint-plugin-vue": "^9.6.0",
+    "eslint-plugin-vue": "^9.7.0",
     "html-webpack-plugin": "^5.5.0",
     "postcss": "^8.4.18",
     "postcss-html": "^1.5.0",
     "prettier": "2.7.1",
-    "sass": "^1.55.0",
+    "sass": "^1.56.0",
     "sass-loader": "^10.3.1",
     "script-ext-html-webpack-plugin": "^2.1.5",
-    "stylelint": "^14.14.0",
+    "stylelint": "^14.14.1",
     "stylelint-config-prettier": "^9.0.3",
     "stylelint-config-recess-order": "^3.0.0",
     "stylelint-config-recommended-vue": "^1.4.0",
-    "stylelint-config-standard-scss": "^5.0.0",
+    "stylelint-config-standard-scss": "^6.0.0",
     "stylelint-declaration-block-no-ignored-properties": "^2.6.0",
     "stylelint-webpack-plugin": "^3.3.0",
     "svg-sprite-loader": "^6.0.11",

+ 13 - 0
src/api/list.js

@@ -87,3 +87,16 @@ export function GetMyCourseList_TaskBelong(data) {
     data
   });
 }
+
+/**
+ * 得到我的任务列表(用于主页显示)【课节分组模式,新版任务列表】
+ * @param {Object} data
+ */
+export function GetMyTaskList_CSItemGroup(data) {
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params: getRequestParams('cominfo_query-task_query-GetMyTaskList_CSItemGroup'),
+    data
+  });
+}

+ 0 - 1
src/store/modules/app.js

@@ -1,7 +1,6 @@
 import { app } from '@/store/mutation-types';
 import { getConfig } from '@/utils/auth';
 import { taskModeList } from '../data';
-import { isAbnormalVal } from '@/utils/validate';
 
 const liveStorage = 'liveDevice';
 

+ 2 - 2
src/styles/mixin.scss

@@ -29,8 +29,8 @@
   .el-table {
     width: 100%;
 
-    &__header th:first-child,
-    &__body .el-table__row > td:first-child {
+    :deep &__header th:first-child,
+    :deep &__body .el-table__row > td:first-child {
       padding-left: 20px;
       font-weight: 700;
     }

+ 57 - 295
src/views/main/TaskList.vue

@@ -2,14 +2,9 @@
   <div class="tasks">
     <div class="tasks-left">
       <!-- 菜单 -->
-      <main-menu cur-tab="TaskList" />
+      <MainMenu cur-tab="TaskList" />
       <!-- 日历 -->
-      <monthly-calendar
-        ref="calendar"
-        :date-stamp="dateStamp"
-        @changeTimeUnit="changeTimeUnit"
-        @changeDate="changeDate"
-      />
+      <MonthlyCalendar ref="calendar" :date-stamp="dateStamp" @changeTimeUnit="init" @changeDate="init" />
       <!-- 通知 -->
       <div class="notice">
         <div class="notice-title">
@@ -68,248 +63,65 @@
       </div>
 
       <div class="task-container">
-        <ul v-for="({ task_list, date_stamp }, i) in task_group_list" :key="i" class="task-list">
-          <li v-if="time_unit === 'MONTH'" class="date-stamp">
-            {{ date_stamp }}
-          </li>
-          <li
-            v-for="{
-              id,
-              cs_item_name,
-              time_type,
-              course_id: cid,
-              course_name,
-              teaching_type,
-              time_space_view_txt,
-              name
-            } in task_list"
-            :key="id"
-            class="task-item"
-            :style="getItemStyle(cid)"
-            @click="taskLink_outside(id)"
-          >
-            <div class="task-item-top">
-              <svg-icon icon-class="arrival" :style="getItemIconStyle(cid)" />
-              <span class="cs-item-name">
-                {{ cs_item_name }} - {{ name }}
-                <span v-if="teaching_type === 10" class="enter-live" @click.stop="taskLink(teaching_type, id)">
-                  {{ $t('Key616') }} >
-                </span>
-              </span>
-              <span
-                class="task-button"
-                :style="{ 'background-color': buttonColorList.get(time_type) }"
-                @click.stop="taskLink(teaching_type, id)"
-              >
-                {{ $t(getTimeTypeName(time_type)) }}{{ $t('Key289') }}
-              </span>
-            </div>
-            <div class="task-item-bottom">
-              <div>
-                {{ course_name }}
-              </div>
-              <div class="time-txt">
-                {{ time_space_view_txt }}
-              </div>
-            </div>
-          </li>
-        </ul>
+        <OldTaskList v-if="task_mode === taskModeList[0]" :task-group-list="task_group_list" :time-unit="time_unit" />
+        <TaskList v-else-if="task_mode === taskModeList[1]" :task-group-list="task_group_list" :time-unit="time_unit" />
       </div>
     </div>
   </div>
 </template>
 
 <script>
-import MainMenu from './components/MainMenu.vue';
-import { PageQueryMyMessageList, GetMyTaskList } from '@/api/table';
-import { CreateEnterLiveRoomSession } from '@/api/live';
-import { ReadMyMessage, GetMyBookBuyStatus_CurTaskCoursewareBook } from '@/api/user';
-import { colorMatching, buttonColorList } from './data';
-import { taskTimeList } from '@/common/data';
-import { GetMyCourseList_TaskBelong } from '@/api/list';
-import MonthlyCalendar from './components/MonthlyCalendar.vue';
-
 export default {
-  name: 'TaskList',
-  components: {
-    MonthlyCalendar,
-    MainMenu
-  },
-  data() {
-    const date = this.$route.query.dateStamp;
-    return {
-      dateStamp: date ? new Date(date) : undefined,
-      colorMatching,
-      buttonColorList,
-      taskTimeList,
-      course_id: '',
-      selected: '',
-      timeType: -1,
-      task_group_list: [],
-      message_list: [],
-      course_list: [],
-      // 课程 id 列表,用于颜色显示
-      courseIdList: []
-    };
-  },
-  computed: {
-    time_unit() {
-      return this.$refs.calendar.time_unit;
-    }
-  },
-  created() {
-    PageQueryMyMessageList({
-      read_status: -1,
-      message_type: -1,
-      page_capacity: 5,
-      cur_page: 1
-    }).then(({ message_list }) => {
-      this.message_list = message_list;
-    });
-  },
-  mounted() {
-    this.init();
-  },
-  methods: {
-    getTimeTypeName(type) {
-      if (type === 0) return 'Key292';
-      if (type === 1) return 'Key293';
-      if (type === 2) return 'Key294';
-      return '';
-    },
-
-    getMyCourseList_TaskBelong() {
-      const { curYear, curMonth, focusDate } = this.$refs.calendar;
-      GetMyCourseList_TaskBelong({
-        time_unit: this.time_unit,
-        date_stamp: `${curYear}-${curMonth}-${focusDate}`,
-        month_stamp: `${curYear}-${curMonth}`
-      }).then(({ course_list }) => {
-        this.course_list = course_list;
-      });
-    },
-
-    getMyTaskList() {
-      const { curYear, curMonth, focusDate } = this.$refs.calendar;
-      GetMyTaskList({
-        time_unit: this.time_unit,
-        date_stamp: `${curYear}-${curMonth}-${focusDate}`,
-        month_stamp: `${curYear}-${curMonth}`,
-        time_type: this.timeType,
-        course_id: this.course_id
-      }).then(({ task_group_list }) => {
-        this.task_group_list = task_group_list;
-      });
-    },
-
-    // 改变任务时间类型
-    changeTaskTime(constant) {
-      this.timeType = constant;
-      this.getMyTaskList();
-    },
-
-    changeTimeUnit() {
-      this.init();
-    },
-
-    changeDate() {
-      this.init();
-    },
-
-    init() {
-      this.course_id = '';
-      this.getMyTaskList();
-      this.getMyCourseList_TaskBelong();
-    },
-
-    changeCourse() {
-      this.getMyTaskList();
-    },
-
-    taskLink(type, task_id) {
-      const userType = this.$store.state.user.user_type;
-      GetMyBookBuyStatus_CurTaskCoursewareBook({ task_id }).then(({ is_buy_all }) => {
-        if (is_buy_all === 'false' && userType === 'STUDENT') {
-          return this.$message.warning(this.$i18n.t('Key635'));
-        }
+  name: 'TaskList'
+};
+</script>
 
-        if (type === 10) {
-          CreateEnterLiveRoomSession({
-            task_id
-          }).then(
-            ({
-              live_room_sys_user_id,
-              room_id,
-              session_id,
-              room_user_id,
-              is_remind_quota_lave_online,
-              quota_lave_online
-            }) => {
-              if (is_remind_quota_lave_online === 'true') {
-                this.$message({
-                  type: 'warning',
-                  message: `直播配额还剩余${quota_lave_online}小时`,
-                  duration: 5000
-                });
-              }
-              this.$router.push({
-                path: `/live/${userType === 'TEACHER' ? 'teacher' : 'student'}`,
-                query: { live_room_sys_user_id, room_id, session_id, task_id, room_user_id }
-              });
-            }
-          );
-        } else {
-          this.$router.push(`/task_detail/${userType === 'STUDENT' ? 'student' : 'teacher'}/${task_id}`);
-        }
-      });
-    },
-
-    taskLink_outside(task_id) {
-      GetMyBookBuyStatus_CurTaskCoursewareBook({ task_id }).then(({ is_buy_all }) => {
-        const userType = this.$store.state.user.user_type;
-        if (is_buy_all === 'false' && userType === 'STUDENT') {
-          return this.$message.warning(this.$i18n.t('Key635'));
-        }
-        this.$router.push(`/task_detail/${userType === 'STUDENT' ? 'student' : 'teacher'}/${task_id}`);
-      });
-    },
-
-    readMyMessage(id, source_entity_id, message_type) {
-      if (message_type === 201) return;
-      ReadMyMessage({ id }).then(() => {
-        this.taskLink_outside(source_entity_id);
-      });
-    },
-
-    getItemStyle(id) {
-      if (!this.courseIdList.includes(id)) {
-        this.courseIdList.push(id);
-      }
-      const i = this.courseIdList.indexOf(id) % 7;
-
-      return {
-        'background-color': colorMatching[i].background,
-        color: colorMatching[i].main,
-        border: `1px solid ${colorMatching[i].border}`
-      };
-    },
-
-    getItemIconStyle(id) {
-      if (!this.courseIdList.includes(id)) {
-        this.courseIdList.push(id);
-      }
-      const i = this.courseIdList.indexOf(id) % 7;
+<script setup>
+import { ref, inject } from 'vue';
+import { PageQueryMyMessageList } from '@/api/table';
+import { ReadMyMessage } from '@/api/user';
+import { taskTimeList } from '@/common/data';
+import { useRoute, useRouter } from 'vue-router/composables';
+import { taskModeList } from '@/store/data';
+import { useTaskList, useTaskLink } from './components/TaskList';
 
-      return {
-        color: colorMatching[i].main
-      };
-    },
+import MainMenu from './components/MainMenu.vue';
+import MonthlyCalendar from './components/MonthlyCalendar.vue';
+import OldTaskList from './components/OldTaskList.vue';
+import TaskList from './components/TaskList.vue';
+
+const route = useRoute();
+const date = route.query.dateStamp;
+let dateStamp = date ? new Date(date) : undefined;
+
+// 分页查询消息列表
+let message_list = ref([]);
+PageQueryMyMessageList({
+  read_status: -1,
+  message_type: -1,
+  page_capacity: 5,
+  cur_page: 1
+}).then(({ message_list: list }) => {
+  message_list.value = list;
+});
+
+let calendar = ref();
+let { task_group_list, task_mode, time_unit, course_id, timeType, course_list, changeTaskTime, changeCourse, init } =
+  useTaskList(calendar);
+
+const $t = inject('$t');
+const router = useRouter();
+let { taskLink_outside } = useTaskLink(router);
+function readMyMessage(id, source_entity_id, message_type) {
+  if (message_type === 201) return;
+  ReadMyMessage({ id }).then(() => {
+    taskLink_outside(source_entity_id);
+  });
+}
 
-    goPersonal() {
-      window.location.href = `/GCLS-Personal/#/EnterSys`;
-    }
-  }
-};
+function goPersonal() {
+  window.location.href = `/GCLS-Personal/#/EnterSys`;
+}
 </script>
 
 <style lang="scss" scoped>
@@ -458,65 +270,15 @@ export default {
       }
     }
 
-    .task-container {
-      min-height: calc(100% - 50px);
-
-      .task-list {
-        li.date-stamp {
-          margin-top: 16px;
-          margin-bottom: -8px;
-          font-weight: 700;
-        }
-
-        .task-item {
-          padding: 16px 24px;
-          margin-top: 16px;
-          cursor: pointer;
-          border-radius: 8px;
-
-          &-top {
-            display: flex;
-            margin-bottom: 8px;
-
-            .cs-item-name {
-              flex: 1;
-              margin-left: 10px;
-
-              .enter-live {
-                margin-left: 12px;
-                color: #808080;
-              }
-            }
-
-            .task-button {
-              padding: 4px 8px;
-              color: #fff;
-              border-radius: 8px;
-            }
-          }
-
-          &-bottom {
-            font-size: 14px;
-            color: #808080;
-
-            .time-txt {
-              margin-top: 8px;
-              color: #000;
-            }
-          }
-        }
+    :deep .select-course {
+      .el-input__inner {
+        border-top-left-radius: 0;
+        border-bottom-left-radius: 0;
       }
     }
-  }
-}
-</style>
 
-<style lang="scss">
-.tasks {
-  .el-select.select-course {
-    .el-input__inner {
-      border-top-left-radius: 0;
-      border-bottom-left-radius: 0;
+    .task-container {
+      min-height: calc(100% - 50px);
     }
   }
 }

+ 74 - 89
src/views/main/TemplateList.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="template">
-    <main-menu cur-tab="TemplateList" />
+    <MainMenu cur-tab="TemplateList" />
     <!-- 查询条件 -->
     <div class="template-search">
       <div>
@@ -28,7 +28,7 @@
         </el-button>
       </div>
       <div class="template-container-list">
-        <el-table :data="courseList">
+        <el-table :data="list">
           <el-table-column prop="name" :label="$t('Key134')" width="320" />
           <el-table-column :label="$t('Key250')" width="210">
             <template slot-scope="{ row }">
@@ -76,106 +76,91 @@
       layout="prev, pager, next, total, sizes, jumper"
       :total="total_count"
       :current-page="cur_page"
-      @prev-click="changePage"
-      @next-click="changePage"
-      @current-change="changePage"
-      @size-change="changePageSize"
+      @prev-click="changePage($event, queryCourseList)"
+      @next-click="changePage($event, queryCourseList)"
+      @current-change="changePage($event, queryCourseList)"
+      @size-change="changePageSize($event, queryCourseList)"
     />
   </div>
 </template>
 
 <script>
-import MainMenu from './components/MainMenu.vue';
+export default {
+  name: 'TemplateList'
+};
+</script>
+
+<script setup>
+import { ref, inject } from 'vue';
 import { PageQueryCourseList } from '@/api/table';
 import { ReleaseCourse, DeleteCourse, IsHasEditDestCoursePopedom } from '@/api/course';
+import { useList } from '@/utils/list';
+import { useRouter } from 'vue-router/composables';
+import { Message } from 'element-ui';
 
-export default {
-  name: 'TemplateList',
-  components: {
-    MainMenu
-  },
-  data() {
-    return {
-      // 查询条件
-      template_name: '',
-      page_capacity: 10,
-      cur_page: 0,
-      total_count: 0,
-      release_status: -1,
-      releaseStatusList: [
-        {
-          name: 'Key110',
-          value: -1
-        },
-        {
-          name: 'Key129',
-          value: 1
-        },
-        {
-          name: 'Key217',
-          value: 0
-        }
-      ],
-      // 课程列表
-      courseList: []
-    };
+import MainMenu from './components/MainMenu.vue';
+
+let template_name = ref('');
+let release_status = ref(-1);
+// 发布状态列表
+const releaseStatusList = [
+  {
+    name: 'Key110',
+    value: -1
   },
-  created() {
-    this.queryCourseList();
+  {
+    name: 'Key129',
+    value: 1
   },
-  methods: {
-    changePage(newPage) {
-      this.cur_page = newPage;
-      this.queryCourseList();
-    },
-    changePageSize(pageSize) {
-      this.page_capacity = pageSize;
-      this.queryCourseList();
-    },
-    queryCourseList() {
-      PageQueryCourseList({
-        is_template: true,
-        name: this.template_name,
-        page_capacity: this.page_capacity,
-        cur_page: this.cur_page,
-        release_status: this.release_status
-      }).then(({ course_list, total_count }) => {
-        this.courseList = course_list;
-        this.total_count = total_count;
-      });
-    },
-
-    edit(id) {
-      IsHasEditDestCoursePopedom({ id }).then(({ is_has_popedom }) => {
-        if (is_has_popedom === 'true') {
-          return this.$router.push(`/create_course_step_table/course_info?id=${id}&is_template=true`);
-        }
-        this.$message.warning(this.$i18n.t('Key620'));
-      });
-    },
-
-    releaseCourse(course_id, is_release) {
-      ReleaseCourse({ course_id, is_release }).then(() => {
-        this.queryCourseList();
-        this.$message.success(is_release ? this.$i18n.t('Key621') : this.$i18n.t('Key622'));
-      });
-    },
-
-    deleteCourse(id) {
-      DeleteCourse({ id }).then(() => {
-        this.queryCourseList();
-        this.$message.success(this.$i18n.t('Key638'));
-      });
-    },
-
-    changeTab(tab) {
-      this.$emit('changeTab', tab);
-    }
+  {
+    name: 'Key217',
+    value: 0
   }
-};
+];
+
+let { page_capacity, cur_page, total_count, list, changePage, changePageSize } = useList();
+
+function queryCourseList() {
+  PageQueryCourseList({
+    is_template: true,
+    name: template_name.value,
+    page_capacity: page_capacity.value,
+    cur_page: cur_page.value,
+    release_status: release_status.value
+  }).then(({ course_list, total_count: total }) => {
+    list.value = course_list;
+    total_count.value = total;
+  });
+}
+queryCourseList();
+
+const router = useRouter();
+let $t = inject('$t');
+function edit(id) {
+  IsHasEditDestCoursePopedom({ id }).then(({ is_has_popedom }) => {
+    if (is_has_popedom === 'true') {
+      return router.push(`/create_course_step_table/course_info?id=${id}&is_template=true`);
+    }
+    Message.warning($t('Key620'));
+  });
+}
+
+function releaseCourse(course_id, is_release) {
+  ReleaseCourse({ course_id, is_release }).then(() => {
+    queryCourseList();
+    Message.success(is_release ? $t('Key621') : $t('Key622'));
+  });
+}
+
+function deleteCourse(id) {
+  DeleteCourse({ id }).then(() => {
+    queryCourseList();
+    Message.success($t('Key638'));
+  });
+}
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 @import '~@/styles/mixin';
 
 .template {

+ 34 - 13
src/views/main/components/MainMenu.vue

@@ -14,22 +14,43 @@
 </template>
 
 <script>
-import { getMenuList } from '../data';
-
 export default {
-  inject: ['changeTab'],
-  props: {
-    curTab: {
-      default: 'TaskList',
-      type: String
-    }
+  name: 'MainMenu'
+};
+</script>
+
+<script setup>
+import { ref, inject } from 'vue';
+import store from '@/store';
+
+const changeTab = inject('changeTab');
+
+defineProps({
+  curTab: {
+    default: 'TaskList',
+    type: String
+  }
+});
+
+const popedom_code_list = store.state.user.popedom_code_list;
+const isStudent = store.state.user.user_type === 'STUDENT';
+let menuList = ref([
+  {
+    name: 'Key289',
+    tab: 'TaskList',
+    isShow: isStudent || popedom_code_list.includes(2000001)
   },
-  data() {
-    return {
-      menuList: getMenuList()
-    };
+  {
+    name: 'Key215',
+    tab: 'CurriculaList',
+    isShow: isStudent || popedom_code_list.includes(2000001)
+  },
+  {
+    name: 'Key290',
+    tab: 'TemplateList',
+    isShow: !isStudent && popedom_code_list.includes(2000002)
   }
-};
+]);
 </script>
 
 <style lang="scss" scoped>

+ 265 - 0
src/views/main/components/MonthlyCalendar.js

@@ -0,0 +1,265 @@
+import { GetMyTaskDailyDistribution } from '@/api/user';
+import { ref, watchEffect, nextTick } from 'vue';
+
+import dayjs from 'dayjs';
+
+export const weekList = [
+  {
+    name: '日',
+    label: 'Sun'
+  },
+  {
+    name: '一',
+    label: 'Mon'
+  },
+  {
+    name: '二',
+    label: 'Tue'
+  },
+  {
+    name: '三',
+    label: 'Wed'
+  },
+  {
+    name: '四',
+    label: 'Thu'
+  },
+  {
+    name: '五',
+    label: 'Fri'
+  },
+  {
+    name: '六',
+    label: 'Sat'
+  }
+];
+
+export const monthList = [
+  {
+    name: '01月',
+    label: 'Jan'
+  },
+  {
+    name: '02月',
+    label: 'Feb'
+  },
+  {
+    name: '03月',
+    label: 'Mar'
+  },
+  {
+    name: '04月',
+    label: 'Apr'
+  },
+  {
+    name: '05月',
+    label: 'May'
+  },
+  {
+    name: '06月',
+    label: 'Jun'
+  },
+  {
+    name: '07月',
+    label: 'Jul'
+  },
+  {
+    name: '08月',
+    label: 'Aug'
+  },
+  {
+    name: '09月',
+    label: 'Sep'
+  },
+  {
+    name: '10月',
+    label: 'Oct'
+  },
+  {
+    name: '11月',
+    label: 'Nov'
+  },
+  {
+    name: '12月',
+    label: 'Dec'
+  }
+];
+
+export const modeList = [
+  {
+    type: 'DAY',
+    name: 'Key311'
+  },
+  {
+    type: 'MONTH',
+    name: 'Key310'
+  }
+];
+
+/**
+ * 日历方法
+ * @param {Date} dateStamp
+ * @param {Emits} emits
+ */
+export function useMonthlyCalendar(dateStamp, emits) {
+  let focusDate = ref(dateStamp.getDate());
+  let focusMonth = ref(0);
+  let curYear = ref(dateStamp.getFullYear());
+  let curMonth = ref(dateStamp.getMonth() + 1);
+  let calendarStyle = ref('');
+
+  const DAY = modeList[0].type;
+  const MONTH = modeList[1].type;
+
+  let time_unit = ref(modeList[0].type);
+  let dateArr = ref([]);
+  watchEffect(() => {
+    if (time_unit.value === DAY) {
+      return (calendarStyle.value = `40px repeat(${dateArr.value.length > 35 ? 6 : 5}, 1fr) / repeat(7, 1fr)`);
+    }
+    if (time_unit.value === MONTH) return (calendarStyle.value = `repeat(4, 1fr) / repeat(3, 1fr)`);
+  });
+
+  let date = ref(`${dateStamp.getFullYear()}-${dateStamp.getMonth() + 1}`);
+  let taskDailyDistribution = ref({}); // 任务每日分布
+  watchEffect(() => {
+    const arr = date.value.split('-').map((item) => Number(item));
+    curYear.value = arr[0];
+    curMonth.value = arr[1];
+    focusMonth.value = arr[1] - 1;
+    GetMyTaskDailyDistribution({ month_stamp: date.value }).then(({ status, ...data }) => {
+      if (status !== 1) return;
+      const taskDailyArr = {};
+      for (const [key, value] of Object.entries(data)) {
+        taskDailyArr[key.slice(5)] = value;
+      }
+      taskDailyDistribution.value = taskDailyArr;
+    });
+  });
+
+  // 得到日历所需数组
+  function getDateArr() {
+    const daysInMonth = dayjs(date.value).daysInMonth();
+    const dayOfWeek = dayjs(`${date.value}-1`).day();
+    const curMonth = dayjs(date.value).month();
+    const curYear = dayjs(date.value).year();
+    const lastDays = dayjs(curMonth === 0 ? `${curYear - 1}-12` : `${curYear}-${curMonth}`).daysInMonth();
+
+    const cDate = new Date();
+    const curDate = cDate.getDate();
+    const isThisMonth = curMonth === cDate.getMonth() && curYear === cDate.getFullYear();
+
+    let arr = [];
+    // 是否有上个月
+    for (let i = 0; i < dayOfWeek; i++) {
+      arr[i] = {
+        key: `last-${i}`,
+        month: (curMonth === 0 ? 11 : curMonth - 1) + 1,
+        day: lastDays - dayOfWeek + i + 1,
+        isCurMonth: false,
+        isToday: false
+      };
+    }
+    // 本月
+    for (let j = 1; j <= daysInMonth; j++) {
+      arr[j + dayOfWeek - 1] = {
+        key: `cur-${j}`,
+        month: curMonth + 1,
+        day: j,
+        isCurMonth: true,
+        isToday: j === curDate && isThisMonth
+      };
+    }
+    if (arr.length === 35) return (dateArr.value = arr);
+    // 下月
+    let next = (arr.length < 35 ? 35 : 42) - dayOfWeek - daysInMonth;
+    for (let k = 1; k <= next; k++) {
+      arr.push({
+        key: `next-${k}`,
+        month: (curMonth === 11 ? 1 : curMonth + 1) + 1,
+        day: k,
+        isCurMonth: false,
+        isToday: false
+      });
+    }
+    dateArr.value = arr;
+  }
+  getDateArr();
+
+  // 返回今天
+  function backToday() {
+    const curDate = new Date();
+    date.value = `${curDate.getFullYear()}-${curDate.getMonth() + 1}`;
+    focusDate.value = curDate.getDate();
+    focusMonth.value = curDate.getMonth();
+    emits('changeDate');
+    getDateArr();
+  }
+
+  // 修改月份
+  function changeMonth(type) {
+    const curMonth = dayjs(date.value).month();
+    const curYear = dayjs(date.value).year();
+    if (type === 'pre' && time_unit.value === DAY) {
+      date.value = curMonth === 0 ? `${curYear - 1}-12` : `${curYear}-${curMonth}`;
+    }
+    if (type === 'pre' && time_unit.value === MONTH) {
+      date.value = `${curYear - 1}-${curMonth + 1}`;
+    }
+
+    if (type === 'next' && time_unit.value === DAY) {
+      date.value = curMonth === 11 ? `${curYear + 1}-1` : `${curYear}-${curMonth + 2}`;
+    }
+    if (type === 'next' && time_unit.value === MONTH) {
+      date.value = `${curYear + 1}-${curMonth + 1}`;
+    }
+    nextTick(() => {
+      emits('changeDate');
+    });
+    getDateArr();
+  }
+
+  /**
+   * 改变显示方式 日/月
+   */
+  function changeMenu(type) {
+    time_unit.value = type;
+    emits('changeTimeUnit');
+  }
+
+  function selectDate(number, isCurMonth) {
+    if (time_unit.value === DAY) {
+      focusDate.value = number;
+    }
+    if (!isCurMonth) {
+      return changeMonth(number < 7 ? 'next' : 'pre');
+    }
+    emits('changeDate');
+  }
+
+  function selectMonth(number) {
+    date.value = `${curYear.value}-${number + 1}`;
+    focusMonth.value = number;
+    nextTick(() => {
+      emits('changeDate');
+    });
+  }
+
+  return {
+    DAY,
+    MONTH,
+    time_unit,
+    curYear,
+    curMonth,
+    focusDate,
+    calendarStyle,
+    dateArr,
+    taskDailyDistribution,
+    focusMonth,
+    backToday,
+    changeMonth,
+    changeMenu,
+    selectDate,
+    selectMonth
+  };
+}

+ 41 - 187
src/views/main/components/MonthlyCalendar.vue

@@ -3,9 +3,9 @@
     <div class="monthly-calendar-top">
       <svg-icon icon-class="calendar" class-name="svg-normal" />
       <span class="date" v-text="`${curYear}${time_unit === DAY ? `-${curMonth}` : ''}`"></span>
-      <i class="el-icon-arrow-left" @click="changeDate('pre')"></i>
+      <i class="el-icon-arrow-left" @click="changeMonth('pre')"></i>
       <span class="today-dot" @click="backToday"></span>
-      <i class="el-icon-arrow-right" @click="changeDate('next')"></i>
+      <i class="el-icon-arrow-right" @click="changeMonth('next')"></i>
     </div>
     <!-- 日历主内容 -->
     <div class="monthly-calendar-container" :style="{ 'grid-template': calendarStyle }">
@@ -77,195 +77,49 @@
 </template>
 
 <script>
-import dayjs from 'dayjs';
-import { weekList, modeList, monthList } from './calendarData';
-import { GetMyTaskDailyDistribution } from '@/api/user';
-
 export default {
-  props: {
-    dateStamp: {
-      type: Date,
-      default: () => {
-        return new Date();
-      }
-    }
-  },
-  data() {
-    return {
-      focusDate: 0,
-      focusMonth: 0,
-      dateArr: [],
-      weekList,
-      monthList,
-      date: '',
-      curYear: this.dateStamp.getFullYear(),
-      curMonth: this.dateStamp.getMonth() + 1,
-      time_unit: modeList[0].type,
-      DAY: modeList[0].type,
-      MONTH: modeList[1].type,
-      modeList,
-      calendarStyle: '',
-      // 任务每日分布
-      taskDailyDistribution: {},
-      taskDailyClass: new Map([
-        [0, ''],
-        [1, 'has-task'],
-        [2, 'task-completed']
-      ])
-    };
-  },
-  watch: {
-    time_unit(newVal) {
-      if (newVal === this.DAY) {
-        return (this.calendarStyle = `40px repeat(${this.dateArr.length > 35 ? 6 : 5}, 1fr) / repeat(7, 1fr)`);
-      }
-      if (newVal === this.MONTH) return (this.calendarStyle = `repeat(4, 1fr) / repeat(3, 1fr)`);
-    },
-    dateArr(newVal) {
-      if (this.time_unit === this.DAY) {
-        this.calendarStyle = `40px repeat(${newVal.length > 35 ? 6 : 5}, 1fr) / repeat(7, 1fr)`;
-      }
-    },
-    date(newVal) {
-      const arr = newVal.split('-').map((item) => Number(item));
-      this.curYear = arr[0];
-      this.curMonth = arr[1];
-      this.focusMonth = arr[1] - 1;
-      GetMyTaskDailyDistribution({ month_stamp: newVal }).then(({ status, ...data }) => {
-        const taskDailyArr = {};
-        for (const [key, value] of Object.entries(data)) {
-          taskDailyArr[key.slice(5)] = value;
-        }
-        if (status === 1) this.taskDailyDistribution = taskDailyArr;
-      });
-    }
-  },
-  created() {
-    this.date = `${this.dateStamp.getFullYear()}-${this.dateStamp.getMonth() + 1}`;
-    this.getDateArr();
-    this.focusDate = this.dateStamp.getDate();
-  },
-  methods: {
-    // 返回今天
-    backToday() {
-      const date = new Date();
-      this.date = `${date.getFullYear()}-${date.getMonth() + 1}`;
-      this.focusDate = date.getDate();
-      this.focusMonth = date.getMonth();
-      this.$emit('changeDate');
-      this.getDateArr();
-    },
-
-    changeDate(type) {
-      const curMonth = dayjs(this.date).month();
-      const curYear = dayjs(this.date).year();
-      if (type === 'pre' && this.time_unit === this.DAY) {
-        this.date = curMonth === 0 ? `${curYear - 1}-12` : `${curYear}-${curMonth}`;
-      }
-      if (type === 'pre' && this.time_unit === this.MONTH) {
-        this.date = `${curYear - 1}-${curMonth + 1}`;
-      }
+  name: 'MonthlyCalendar'
+};
+</script>
 
-      if (type === 'next' && this.time_unit === this.DAY) {
-        this.date = curMonth === 11 ? `${curYear + 1}-1` : `${curYear}-${curMonth + 2}`;
-      }
-      if (type === 'next' && this.time_unit === this.MONTH) {
-        this.date = `${curYear + 1}-${curMonth + 1}`;
-      }
-      this.$nextTick(() => {
-        this.$emit('changeDate');
-      });
-      this.getDateArr();
-    },
-
-    changeMenu(type) {
-      this.time_unit = type;
-      this.$emit('changeTimeUnit');
-    },
-
-    selectDate(number, isCurMonth) {
-      if (this.time_unit === this.DAY) {
-        this.focusDate = number;
-      }
-      if (!isCurMonth) {
-        return this.changeDate(number < 7 ? 'next' : 'pre');
-      }
-      this.$emit('changeDate');
-    },
-    selectMonth(number) {
-      this.date = `${this.curYear}-${number + 1}`;
-      this.focusMonth = number;
-      this.$nextTick(() => {
-        this.$emit('changeDate');
-      });
-    },
-
-    // 得到日历所需数组
-    getDateArr() {
-      const daysInMonth = dayjs(this.date).daysInMonth();
-      const dayOfWeek = dayjs(`${this.date}-1`).day();
-      const curMonth = dayjs(this.date).month();
-      const curYear = dayjs(this.date).year();
-      const lastDays = dayjs(curMonth === 0 ? `${curYear - 1}-12` : `${curYear}-${curMonth}`).daysInMonth();
-
-      const date = new Date();
-      const curDate = date.getDate();
-      const isThisMonth = curMonth === date.getMonth() && curYear === date.getFullYear();
-
-      const arr = [];
-      // 是否有上个月
-      for (let i = 0; i < dayOfWeek; i++) {
-        arr[i] = {
-          key: `last-${i}`,
-          month: (curMonth === 0 ? 11 : curMonth - 1) + 1,
-          day: lastDays - dayOfWeek + i + 1,
-          isCurMonth: false,
-          isToday: false
-        };
-      }
-      // 本月
-      for (let j = 1; j <= daysInMonth; j++) {
-        arr[j + dayOfWeek - 1] = {
-          key: `cur-${j}`,
-          month: curMonth + 1,
-          day: j,
-          isCurMonth: true,
-          isToday: j === curDate && isThisMonth
-        };
-      }
-      if (arr.length === 35) {
-        this.dateArr = arr;
-        return;
-      }
-      // 下月
-      if (arr.length < 35) {
-        for (let k = 1; k <= 35 - (dayOfWeek + daysInMonth); k++) {
-          arr.push({
-            key: `next-${k}`,
-            month: (curMonth === 11 ? 1 : curMonth + 1) + 1,
-            day: k,
-            isCurMonth: false,
-            isToday: false
-          });
-        }
-        this.dateArr = arr;
-        return;
-      }
-      if (arr.length > 35) {
-        for (let k = 1; k <= 42 - (dayOfWeek + daysInMonth); k++) {
-          arr.push({
-            key: `next-${k}`,
-            month: (curMonth === 11 ? 1 : curMonth + 1) + 1,
-            day: k,
-            isCurMonth: false
-          });
-        }
-        this.dateArr = arr;
-        return;
-      }
+<script setup>
+import { useMonthlyCalendar, weekList, monthList, modeList } from './MonthlyCalendar';
+
+const props = defineProps({
+  dateStamp: {
+    type: Date,
+    default: () => {
+      return new Date();
     }
   }
-};
+});
+const emits = defineEmits(['changeDate', 'changeTimeUnit']);
+
+const taskDailyClass = new Map([
+  [0, ''],
+  [1, 'has-task'],
+  [2, 'task-completed']
+]);
+
+let {
+  DAY,
+  MONTH,
+  time_unit,
+  curYear,
+  curMonth,
+  focusDate,
+  calendarStyle,
+  dateArr,
+  taskDailyDistribution,
+  focusMonth,
+  backToday,
+  changeMonth,
+  changeMenu,
+  selectDate,
+  selectMonth
+} = useMonthlyCalendar(props.dateStamp, emits);
+
+defineExpose({ time_unit, curYear, curMonth, focusDate });
 </script>
 
 <style lang="scss" scoped>

+ 121 - 0
src/views/main/components/OldTaskList.vue

@@ -0,0 +1,121 @@
+<template>
+  <div>
+    <ul v-for="({ task_list, date_stamp }, i) in taskGroupList" :key="i" class="task-list">
+      <li v-if="timeUnit === 'MONTH'" class="date-stamp">
+        {{ date_stamp }}
+      </li>
+      <li
+        v-for="{
+          id,
+          cs_item_name,
+          time_type,
+          course_id: cid,
+          course_name,
+          teaching_type,
+          time_space_view_txt,
+          name
+        } in task_list"
+        :key="id"
+        class="task-item"
+        :style="getItemStyle(cid)"
+        @click="taskLink_outside(id)"
+      >
+        <div class="task-item-top">
+          <svg-icon icon-class="arrival" :style="getItemIconStyle(cid)" />
+          <span class="cs-item-name">
+            {{ cs_item_name }} - {{ name }}
+            <span v-if="teaching_type === 10" class="enter-live" @click.stop="taskLink(teaching_type, id)">
+              {{ $t('Key616') }} >
+            </span>
+          </span>
+          <span
+            class="task-button"
+            :style="{ 'background-color': buttonColorList.get(time_type) }"
+            @click.stop="taskLink(teaching_type, id)"
+          >
+            {{ $t(getTimeTypeName(time_type)) }}{{ $t('Key289') }}
+          </span>
+        </div>
+        <div class="task-item-bottom">
+          <div>
+            {{ course_name }}
+          </div>
+          <div class="time-txt">
+            {{ time_space_view_txt }}
+          </div>
+        </div>
+      </li>
+    </ul>
+  </div>
+</template>
+
+<script setup>
+import { inject } from 'vue';
+import { useTaskItem, useTaskLink, buttonColorList, getTimeTypeName } from './TaskList';
+import { useRouter } from 'vue-router/composables';
+
+defineProps({
+  timeUnit: {
+    type: undefined,
+    required: true
+  },
+  taskGroupList: {
+    type: Array,
+    required: true
+  }
+});
+
+const $t = inject('$t');
+let { getItemStyle, getItemIconStyle } = useTaskItem();
+
+const router = useRouter();
+let { taskLink, taskLink_outside } = useTaskLink(router);
+</script>
+
+<style lang="scss" scoped>
+.task-list {
+  li.date-stamp {
+    margin-top: 16px;
+    margin-bottom: -8px;
+    font-weight: 700;
+  }
+
+  .task-item {
+    padding: 16px 24px;
+    margin-top: 16px;
+    cursor: pointer;
+    border-radius: 8px;
+
+    &-top {
+      display: flex;
+      margin-bottom: 8px;
+
+      .cs-item-name {
+        flex: 1;
+        margin-left: 10px;
+
+        .enter-live {
+          margin-left: 12px;
+          color: #808080;
+        }
+      }
+
+      .task-button {
+        padding: 4px 8px;
+        color: #fff;
+        border-radius: 8px;
+      }
+    }
+
+    &-bottom {
+      font-size: 14px;
+      color: #808080;
+
+      .time-txt {
+        margin-top: 8px;
+        color: #000;
+      }
+    }
+  }
+}
+</style>

+ 226 - 0
src/views/main/components/TaskList.js

@@ -0,0 +1,226 @@
+import { ref, computed, inject, onMounted } from 'vue';
+import { GetMyTaskList } from '@/api/table';
+import { GetMyTaskList_CSItemGroup, GetMyCourseList_TaskBelong } from '@/api/list';
+import { GetMyBookBuyStatus_CurTaskCoursewareBook } from '@/api/user';
+import { Message } from 'element-ui';
+import { CreateEnterLiveRoomSession } from '@/api/live';
+import { taskModeList } from '@/store/data';
+
+import store from '@/store';
+
+const colorMatching = [
+  {
+    main: '#3479FF',
+    background: 'rgba(52, 121, 255, 0.05)',
+    border: 'rgba(52, 121, 255, 0.15)'
+  },
+  {
+    main: '#754BEE',
+    background: 'rgba(117, 75, 238, 0.05)',
+    border: 'rgba(117, 75, 238, 0.15)'
+  },
+  {
+    main: '#FF7134',
+    background: 'rgba(255, 52, 52, 0.05)',
+    border: 'rgba(255, 52, 52, 0.15)'
+  },
+  {
+    main: '#56BD05',
+    background: 'rgba(86, 189, 5, 0.05)',
+    border: 'rgba(86, 189, 5, 0.15)'
+  },
+  {
+    main: '#00BD84',
+    background: 'rgba(0, 189, 132, 0.05)',
+    border: 'rgba(0, 189, 132, 0.15)'
+  },
+  {
+    main: '#DF339A',
+    background: 'rgba(223, 51, 154, 0.05)',
+    border: 'rgba(223, 51, 154, 0.15)'
+  },
+  {
+    main: '#CF7B18',
+    background: 'rgba(207, 123, 24, 0.05)',
+    border: 'rgba(207, 123, 24, 0.15)'
+  }
+];
+
+export const buttonColorList = new Map([
+  [0, '#63A1FF'],
+  [1, '#f90'],
+  [2, '#00CD8F']
+]);
+
+/**
+ * 任务列表
+ * @param {ref} calendar
+ */
+export function useTaskList(calendar) {
+  let task_group_list = ref([]);
+  const task_mode = store.state.app.config.task_mode;
+  let course_id = ref('');
+  let timeType = ref(-1);
+  let time_unit = computed(() => calendar.value?.time_unit);
+  let course_list = ref([]);
+
+  function getMyTaskList() {
+    const { curYear, curMonth, focusDate } = calendar.value;
+    const data = {
+      time_unit: time_unit.value,
+      date_stamp: `${curYear}-${curMonth}-${focusDate}`,
+      month_stamp: `${curYear}-${curMonth}`,
+      time_type: timeType.value,
+      course_id: course_id.value
+    };
+    (task_mode === taskModeList[0] ? GetMyTaskList : GetMyTaskList_CSItemGroup)(data).then(
+      ({ task_group_list: list }) => {
+        task_group_list.value = list;
+      }
+    );
+  }
+
+  function getMyCourseList_TaskBelong() {
+    const { curYear, curMonth, focusDate } = calendar.value;
+    GetMyCourseList_TaskBelong({
+      time_unit: time_unit.value,
+      date_stamp: `${curYear}-${curMonth}-${focusDate}`,
+      month_stamp: `${curYear}-${curMonth}`
+    }).then(({ course_list: list }) => {
+      course_list.value = list;
+    });
+  }
+
+  // 改变任务时间类型
+  function changeTaskTime(time_type) {
+    timeType.value = time_type;
+    getMyTaskList();
+  }
+
+  function init() {
+    course_id.value = '';
+    getMyTaskList();
+    getMyCourseList_TaskBelong();
+  }
+
+  onMounted(() => {
+    init();
+  });
+
+  function changeCourse() {
+    getMyTaskList();
+  }
+
+  return {
+    task_group_list,
+    task_mode,
+    timeType,
+    course_id,
+    course_list,
+    time_unit,
+    changeTaskTime,
+    changeCourse,
+    init
+  };
+}
+
+/**
+ * 任务列表项相关
+ */
+export function useTaskItem() {
+  let courseIdList = ref([]); // 课程 id 列表,用于颜色显示
+
+  function getItemStyle(id) {
+    if (!courseIdList.value.includes(id)) courseIdList.value.push(id);
+    const i = courseIdList.value.indexOf(id) % 7;
+
+    return {
+      'background-color': colorMatching[i].background,
+      color: colorMatching[i].main,
+      border: `1px solid ${colorMatching[i].border}`
+    };
+  }
+
+  function getItemIconStyle(id) {
+    if (!courseIdList.value.includes(id)) courseIdList.value.push(id);
+    const i = courseIdList.value.indexOf(id) % 7;
+
+    return {
+      color: colorMatching[i].main
+    };
+  }
+
+  return { getItemStyle, getItemIconStyle };
+}
+
+/**
+ * 任务链接
+ */
+export function useTaskLink(router) {
+  const $t = inject('$t');
+
+  function taskLink(type, task_id) {
+    const userType = store.state.user.user_type;
+    GetMyBookBuyStatus_CurTaskCoursewareBook({ task_id }).then(({ is_buy_all }) => {
+      if (is_buy_all === 'false' && userType === 'STUDENT') {
+        return Message.warning($t('Key635'));
+      }
+
+      if (type === 10) {
+        CreateEnterLiveRoomSession({
+          task_id
+        }).then(
+          ({
+            live_room_sys_user_id,
+            room_id,
+            session_id,
+            room_user_id,
+            is_remind_quota_lave_online,
+            quota_lave_online
+          }) => {
+            if (is_remind_quota_lave_online === 'true') {
+              Message({
+                type: 'warning',
+                message: `直播配额还剩余${quota_lave_online}小时`,
+                duration: 5000
+              });
+            }
+            router.push({
+              path: `/live/${userType === 'TEACHER' ? 'teacher' : 'student'}`,
+              query: { live_room_sys_user_id, room_id, session_id, task_id, room_user_id }
+            });
+          }
+        );
+      } else {
+        router.push(`/task_detail/${userType === 'STUDENT' ? 'student' : 'teacher'}/${task_id}`);
+      }
+    });
+  }
+
+  function taskLink_outside(task_id) {
+    GetMyBookBuyStatus_CurTaskCoursewareBook({ task_id }).then(({ is_buy_all }) => {
+      const userType = store.state.user.user_type;
+      if (is_buy_all === 'false' && userType === 'STUDENT') {
+        return Message.warning($t('Key635'));
+      }
+      router.push(`/task_detail/${userType === 'STUDENT' ? 'student' : 'teacher'}/${task_id}`);
+    });
+  }
+
+  return {
+    taskLink,
+    taskLink_outside
+  };
+}
+
+/**
+ * 得到任务类型名称
+ * @param {Number} type
+ * @returns String
+ */
+export function getTimeTypeName(type) {
+  if (type === 0) return 'Key292';
+  if (type === 1) return 'Key293';
+  if (type === 2) return 'Key294';
+  return '';
+}

+ 134 - 0
src/views/main/components/TaskList.vue

@@ -0,0 +1,134 @@
+<template>
+  <div>
+    <ul class="task-list">
+      <li
+        v-for="({ task_list, cs_item_id, cs_item_name, course_id, course_name, task_time_type }, i) in taskGroupList"
+        :key="i"
+        class="task-item"
+      >
+        <div class="task-item-top">
+          <svg-icon icon-class="arrival" class-name="arrival" :style="getItemIconStyle(course_id)" />
+          <span class="cs-item-name">
+            {{ cs_item_name }}
+          </span>
+          <!-- <span v-if="teaching_type === 10" class="enter-live" @click.stop="taskLink(teaching_type, id)">
+              {{ $t('Key616') }} >
+            </span> -->
+          <span
+            class="task-button"
+            :style="{ 'background-color': buttonColorList.get(task_time_type) }"
+            @click.stop="taskLink(teaching_type, id)"
+          >
+            {{ $t(getTimeTypeName(task_time_type)) }}{{ $t('Key289') }}
+          </span>
+        </div>
+        <div class="task-item-bottom">
+          <div class="course-name">
+            {{ course_name }}
+          </div>
+          <ul>
+            <li v-for="({ id, name }, j) in task_list" :key="id">{{ j + 1 }}. {{ name }}</li>
+          </ul>
+          <!-- <div class="time-txt">时间 {{ time_space_view_txt }}</div> -->
+        </div>
+      </li>
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'TaskList'
+};
+</script>
+
+<script setup>
+import { useRouter } from 'vue-router/composables';
+import { useTaskLink, useTaskItem, getTimeTypeName, buttonColorList } from './TaskList';
+
+defineProps({
+  timeUnit: {
+    type: undefined,
+    required: true
+  },
+  taskGroupList: {
+    type: Array,
+    required: true
+  }
+});
+
+const router = useRouter();
+let { taskLink, taskLink_outside } = useTaskLink(router);
+
+let { getItemIconStyle } = useTaskItem();
+</script>
+
+<style lang="scss" scoped>
+.task-list {
+  li.date-stamp {
+    margin-top: 16px;
+    margin-bottom: -8px;
+    font-weight: 700;
+  }
+
+  .task-item {
+    display: flex;
+    flex-direction: column;
+    row-gap: 8px;
+    padding: 16px 24px;
+    margin-top: 16px;
+    cursor: pointer;
+    border: 1px solid $border-color;
+    border-radius: 8px;
+
+    &-top {
+      display: flex;
+      align-items: center;
+
+      .arrival {
+        width: 20px;
+        height: 20px;
+      }
+
+      .cs-item-name {
+        flex: 1;
+        margin-left: 10px;
+
+        .enter-live {
+          margin-left: 12px;
+          color: #808080;
+        }
+      }
+
+      .task-button {
+        height: 24px;
+        padding: 4px 8px;
+        font-size: 14px;
+        color: #fff;
+        border-radius: 8px;
+      }
+    }
+
+    &-bottom {
+      padding-left: 30px;
+      font-size: 14px;
+
+      .course-name {
+        font-weight: 500;
+        color: #000;
+      }
+
+      ul > li {
+        margin-top: 8px;
+        color: #7f7f7f;
+        cursor: text;
+      }
+
+      .time-txt {
+        margin-top: 8px;
+        color: #808080;
+      }
+    }
+  }
+}
+</style>

+ 0 - 94
src/views/main/components/calendarData.js

@@ -1,94 +0,0 @@
-const weekList = [
-  {
-    name: '日',
-    label: 'Sun'
-  },
-  {
-    name: '一',
-    label: 'Mon'
-  },
-  {
-    name: '二',
-    label: 'Tue'
-  },
-  {
-    name: '三',
-    label: 'Wed'
-  },
-  {
-    name: '四',
-    label: 'Thu'
-  },
-  {
-    name: '五',
-    label: 'Fri'
-  },
-  {
-    name: '六',
-    label: 'Sat'
-  }
-];
-
-const monthList = [
-  {
-    name: '01月',
-    label: 'Jan'
-  },
-  {
-    name: '02月',
-    label: 'Feb'
-  },
-  {
-    name: '03月',
-    label: 'Mar'
-  },
-  {
-    name: '04月',
-    label: 'Apr'
-  },
-  {
-    name: '05月',
-    label: 'May'
-  },
-  {
-    name: '06月',
-    label: 'Jun'
-  },
-  {
-    name: '07月',
-    label: 'Jul'
-  },
-  {
-    name: '08月',
-    label: 'Aug'
-  },
-  {
-    name: '09月',
-    label: 'Sep'
-  },
-  {
-    name: '10月',
-    label: 'Oct'
-  },
-  {
-    name: '11月',
-    label: 'Nov'
-  },
-  {
-    name: '12月',
-    label: 'Dec'
-  }
-];
-
-const modeList = [
-  {
-    type: 'DAY',
-    name: 'Key311'
-  },
-  {
-    type: 'MONTH',
-    name: 'Key310'
-  }
-];
-
-export { weekList, modeList, monthList };

+ 67 - 78
src/views/main/curricula_list/student.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="curricula-student">
-    <main-menu cur-tab="CurriculaList" />
+    <MainMenu cur-tab="CurriculaList" />
     <!-- 查询条件 -->
     <div class="curricula-student-search">
       <div class="curricula-student-search-condition">
@@ -48,7 +48,7 @@
         </div>
       </div>
       <div class="curricula-student-container-list">
-        <el-table :data="courseList">
+        <el-table :data="list">
           <el-table-column prop="course_name" :label="$t('Key203')" width="300" />
           <el-table-column :label="$t('Key617')" prop="teacher_name_desc" width="360" />
           <el-table-column :label="$t('Key250')" width="280">
@@ -77,99 +77,88 @@
       layout="prev, pager, next, total, sizes, jumper"
       :total="total_count"
       :current-page="cur_page"
-      @prev-click="changePage"
-      @next-click="changePage"
-      @current-change="changePage"
-      @size-change="changePageSize"
+      @prev-click="changePage($event, queryMyCourseList)"
+      @next-click="changePage($event, queryMyCourseList)"
+      @current-change="changePage($event, queryMyCourseList)"
+      @size-change="changePageSize($event, queryMyCourseList)"
     />
   </div>
 </template>
 
 <script>
+export default {
+  name: 'CurriculaStudent'
+};
+</script>
+
+<script setup>
+import { ref } from 'vue';
 import { PageQueryMyJoinCourseList_Student } from '@/api/table';
 import {
   GetFinishStatusList_Course,
   GetMyJoinCourseTeacherList_Student,
   GetStudentCourseBuyStatusList
 } from '@/api/select';
-import MainMenu from '../components/MainMenu.vue';
-
-export default {
-  components: { MainMenu },
-  data() {
-    return {
-      search: '',
-      // 完成状态
-      finish_status_list: [],
-      finish_status: -1,
-      // 购买状态
-      buy_status_list: [],
-      buy_status: -1,
-      teacher_list: [],
-      teacher_id: '',
-      page_capacity: 10,
-      cur_page: 1,
-      total_count: 0,
-      courseList: []
-    };
-  },
-  created() {
-    this.initData();
-  },
-  methods: {
-    initData() {
-      GetFinishStatusList_Course().then(({ finish_status_list }) => {
-        this.finish_status_list = finish_status_list;
-      });
-      GetStudentCourseBuyStatusList().then(({ status_list }) => {
-        this.buy_status_list = status_list;
-      });
-      GetMyJoinCourseTeacherList_Student().then(({ teacher_list }) => {
-        this.teacher_list = teacher_list;
-      });
-      this.queryMyCourseList();
-    },
-    changePage(newPage) {
-      this.cur_page = newPage;
-      this.queryMyCourseList();
-    },
-    changePageSize(pageSize) {
-      this.page_capacity = pageSize;
-      this.queryMyCourseList();
-    },
-
-    queryMyCourseList() {
-      PageQueryMyJoinCourseList_Student({
-        teacher_id: this.teacher_id,
-        finish_status: this.finish_status,
-        course_name: this.search,
-        page_capacity: this.page_capacity,
-        cur_page: this.cur_page,
-        buy_status: this.buy_status
-      }).then(({ course_list, total_count }) => {
-        this.courseList = course_list;
-        this.total_count = total_count;
-      });
-    },
+import { useList } from '@/utils/list';
 
-    statusColor(val) {
-      if (val === 50) return '#FF5050';
-      if (val === 51) return '#2ECE5B';
-      if (val === 52) return '#68CEFA';
-    },
+import MainMenu from '../components/MainMenu.vue';
 
-    goLearningCenter() {
-      window.location.href = `/GCLS-LC/#/EnterSys`;
-    },
+// 列表及查询条件
+let { page_capacity, cur_page, total_count, list, changePage, changePageSize } = useList();
+let search = ref('');
+let finish_status = ref(-1);
+let buy_status = ref(-1);
+let teacher_id = ref('');
+function queryMyCourseList() {
+  PageQueryMyJoinCourseList_Student({
+    teacher_id: teacher_id.value,
+    finish_status: finish_status.value,
+    course_name: search.value,
+    page_capacity: page_capacity.value,
+    cur_page: cur_page.value,
+    buy_status: buy_status.value
+  }).then(({ course_list, total_count: total }) => {
+    list.value = course_list;
+    total_count.value = total;
+  });
+}
 
-    changeTab(tab) {
-      this.$emit('changeTab', tab);
-    }
+let finish_status_list = ref([]); // 完成状态列表
+let buy_status_list = ref([]); // 购买状态列表
+let teacher_list = ref([]);
+function initData() {
+  GetFinishStatusList_Course().then(({ finish_status_list: list }) => {
+    finish_status_list.value = list;
+  });
+  GetStudentCourseBuyStatusList().then(({ status_list }) => {
+    buy_status_list.value = status_list;
+  });
+  GetMyJoinCourseTeacherList_Student().then(({ teacher_list: list }) => {
+    teacher_list.value = list;
+  });
+  queryMyCourseList();
+}
+initData();
+
+function statusColor(val) {
+  switch (val) {
+    case 50:
+      return '#FF5050';
+    case 51:
+      return '#2ECE5B';
+    case 52:
+      return '#68CEFA';
+    default:
+      break;
   }
-};
+}
+
+function goLearningCenter() {
+  window.location.href = `/GCLS-LC/#/EnterSys`;
+}
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 @import '~@/styles/mixin';
 
 .curricula-student {

+ 75 - 91
src/views/main/curricula_list/teacher.vue

@@ -36,7 +36,7 @@
         </div>
       </div>
       <div class="curricula-teacher-container-list">
-        <el-table :data="courseList">
+        <el-table :data="list">
           <el-table-column prop="name" :label="$t('Key134')" width="320" />
           <el-table-column :label="$t('Key250')" width="210">
             <template slot-scope="{ row }">
@@ -89,112 +89,96 @@
       layout="prev, pager, next, total, sizes, jumper"
       :total="total_count"
       :current-page="cur_page"
-      @prev-click="changePage"
-      @next-click="changePage"
-      @current-change="changePage"
-      @size-change="changePageSize"
+      @prev-click="changePage($event, queryMyCourseList)"
+      @next-click="changePage($event, queryMyCourseList)"
+      @current-change="changePage($event, queryMyCourseList)"
+      @size-change="changePageSize($event, queryMyCourseList)"
     />
   </div>
 </template>
 
 <script>
-import MainMenu from '../components/MainMenu.vue';
+export default {
+  name: 'CurriculaTeacher'
+};
+</script>
+
+<script setup>
+import { ref, inject } from 'vue';
 import { PageQueryMyCourseList } from '@/api/table';
 import { GetFinishStatusList_Course } from '@/api/select';
 import { ReleaseCourse, DeleteCourse } from '@/api/course';
+import { useList } from '@/utils/list';
+import { useRouter } from 'vue-router/composables';
+import { Message, MessageBox } from 'element-ui';
 
-export default {
-  components: {
-    MainMenu
-  },
-  data() {
-    return {
-      search: '',
-      finish_status_list: [],
-      teacher_list: [],
-      finish_status: -1,
-      page_capacity: 10,
-      cur_page: 1,
-      total_count: 0,
-      courseList: []
-    };
-  },
-  created() {
-    this.queryMyCourseList();
-    this.getFinishStatusList_Course();
-  },
-  methods: {
-    getFinishStatusList_Course() {
-      GetFinishStatusList_Course().then(({ finish_status_list }) => {
-        this.finish_status_list = finish_status_list;
-      });
-    },
-    changePage(newPage) {
-      this.cur_page = newPage;
-      this.queryMyCourseList();
-    },
-    changePageSize(pageSize) {
-      this.page_capacity = pageSize;
-      this.queryMyCourseList();
-    },
-    queryMyCourseList() {
-      PageQueryMyCourseList({
-        finish_status: this.finish_status,
-        name: this.search,
-        page_capacity: this.page_capacity,
-        release_status: -1,
-        cur_page: this.cur_page
-      }).then(({ course_list, total_count }) => {
-        this.courseList = course_list;
-        this.total_count = total_count;
-      });
-    },
+import MainMenu from '../components/MainMenu.vue';
+
+const props = defineProps({
+  ss: {
+    type: Number,
+    required: true
+  }
+});
+console.log(props.ss);
 
-    statusColor(val) {
-      if (val === 0) return '#68CEFA';
-      if (val === 1) return '#2ECE5B';
-      if (val === 3) return '#f90';
-      if (val === 4) return '#4F8EEC';
-    },
+let finish_status_list = ref([]);
+GetFinishStatusList_Course().then(({ finish_status_list: list }) => {
+  finish_status_list.value = list;
+});
 
-    studentList(id) {
-      this.$router.push(`/student_list/index/${id}`);
-    },
-    edit(id) {
-      this.$router.push(`/create_course_step_table/course_info?id=${id}`);
-    },
-    view(id) {
-      this.$router.push(`/GoodsDetail?goods_id=${id}&goods_type=201&readonly=true`);
-    },
+// 列表及查询条件
+let { page_capacity, cur_page, total_count, list, changePage, changePageSize } = useList();
+let search = ref('');
+let finish_status = ref(-1);
+function queryMyCourseList() {
+  PageQueryMyCourseList({
+    finish_status: finish_status.value,
+    name: search.value,
+    page_capacity: page_capacity.value,
+    release_status: -1,
+    cur_page: cur_page.value
+  }).then(({ course_list, total_count: total }) => {
+    list.value = course_list;
+    total_count.value = total;
+  });
+}
+queryMyCourseList();
 
-    releaseCourse(course_id, is_release) {
-      ReleaseCourse({ course_id, is_release }).then(() => {
-        this.queryMyCourseList();
-        this.$message.success(is_release ? this.$i18n.t('Key621') : this.$i18n.t('Key622'));
-      });
-    },
+const router = useRouter();
+function studentList(id) {
+  router.push(`/student_list/index/${id}`);
+}
+function edit(id) {
+  router.push(`/create_course_step_table/course_info?id=${id}`);
+}
+function view(id) {
+  router.push(`/GoodsDetail?goods_id=${id}&goods_type=201&readonly=true`);
+}
 
-    deleteCourse(id) {
-      this.$confirm(this.$i18n.t('Key639'), this.$i18n.t('Key361'), {
-        confirmButtonText: this.$i18n.t('Key94'),
-        cancelButtonText: this.$i18n.t('Key83'),
-        type: 'warning'
-      }).then(() => {
-        DeleteCourse({ id }).then(() => {
-          this.$message.success(this.$i18n.t('Key638'));
-          this.queryMyCourseList();
-        });
-      });
-    },
+const $t = inject('$t');
+function releaseCourse(course_id, is_release) {
+  ReleaseCourse({ course_id, is_release }).then(() => {
+    queryMyCourseList();
+    Message.success(is_release ? $t('Key621') : $t('Key622'));
+  });
+}
 
-    changeTab(tab) {
-      this.$emit('changeTab', tab);
-    }
-  }
-};
+function deleteCourse(id) {
+  MessageBox.confirm($t('Key639'), $t('Key361'), {
+    confirmButtonText: $t('Key94'),
+    cancelButtonText: $t('Key83'),
+    type: 'warning'
+  }).then(() => {
+    DeleteCourse({ id }).then(() => {
+      Message.success($t('Key638'));
+      queryMyCourseList();
+    });
+  });
+}
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 @import '~@/styles/mixin';
 
 .curricula-teacher {

+ 0 - 70
src/views/main/data.js

@@ -1,70 +0,0 @@
-import store from '@/store';
-
-const colorMatching = [
-  {
-    main: '#3479FF',
-    background: 'rgba(52, 121, 255, 0.05)',
-    border: 'rgba(52, 121, 255, 0.15)'
-  },
-  {
-    main: '#754BEE',
-    background: 'rgba(117, 75, 238, 0.05)',
-    border: 'rgba(117, 75, 238, 0.15)'
-  },
-  {
-    main: '#FF7134',
-    background: 'rgba(255, 52, 52, 0.05)',
-    border: 'rgba(255, 52, 52, 0.15)'
-  },
-  {
-    main: '#56BD05',
-    background: 'rgba(86, 189, 5, 0.05)',
-    border: 'rgba(86, 189, 5, 0.15)'
-  },
-  {
-    main: '#00BD84',
-    background: 'rgba(0, 189, 132, 0.05)',
-    border: 'rgba(0, 189, 132, 0.15)'
-  },
-  {
-    main: '#DF339A',
-    background: 'rgba(223, 51, 154, 0.05)',
-    border: 'rgba(223, 51, 154, 0.15)'
-  },
-  {
-    main: '#CF7B18',
-    background: 'rgba(207, 123, 24, 0.05)',
-    border: 'rgba(207, 123, 24, 0.15)'
-  }
-];
-
-const buttonColorList = new Map([
-  [0, '#63A1FF'],
-  [1, '#f90'],
-  [2, '#00CD8F']
-]);
-
-function getMenuList() {
-  const popedom_code_list = store.state.user.popedom_code_list;
-  const isStudent = store.state.user.user_type === 'STUDENT';
-
-  return [
-    {
-      name: 'Key289',
-      tab: 'TaskList',
-      isShow: isStudent || popedom_code_list.includes(2000001)
-    },
-    {
-      name: 'Key215',
-      tab: 'CurriculaList',
-      isShow: isStudent || popedom_code_list.includes(2000001)
-    },
-    {
-      name: 'Key290',
-      tab: 'TemplateList',
-      isShow: !isStudent && popedom_code_list.includes(2000002)
-    }
-  ];
-}
-
-export { colorMatching, getMenuList, buttonColorList };

+ 34 - 37
src/views/main/index.vue

@@ -1,54 +1,51 @@
 <template>
   <main class="main-container">
     <keep-alive>
-      <component :is="currentTabComponent" />
+      <component :is="currentTabComponent" :ss="1" />
     </keep-alive>
   </main>
 </template>
 
 <script>
+export default {
+  name: 'MainPage'
+};
+</script>
+
+<script setup>
+import { ref, provide, computed } from 'vue';
+import { useRoute } from 'vue-router/composables';
+
+import store from '@/store';
+
 import TaskList from './TaskList.vue';
 import TemplateList from './TemplateList.vue';
 import CurriculaListStudent from './curricula_list/student.vue';
 import CurriculaListTeacher from './curricula_list/teacher.vue';
 
-export default {
-  components: {
-    TaskList,
-    TemplateList,
-    CurriculaListStudent,
-    CurriculaListTeacher
-  },
-  provide() {
-    return {
-      changeTab: this.changeTab
-    };
-  },
-  data() {
-    const state = this.$store.state;
-    const popedom_code_list = state.user.popedom_code_list;
-    const isStudent = state.user.user_type === 'STUDENT';
-    function curTab() {
-      return isStudent || popedom_code_list.includes(2000001) ? 'TaskList' : 'TemplateList';
-    }
-    const currentTab = this.$route.query.tab || curTab();
-
-    return {
-      currentTab
-    };
-  },
-  computed: {
-    currentTabComponent() {
-      if (['TemplateList', 'TaskList'].includes(this.currentTab)) return this.currentTab;
-      return `${this.currentTab}${this.$store.state.user.user_type === 'TEACHER' ? 'Teacher' : 'Student'}`;
-    }
-  },
-  methods: {
-    changeTab(tab) {
-      this.currentTab = tab;
-    }
-  }
+const state = store.state;
+const popedom_code_list = state.user.popedom_code_list;
+const isStudent = state.user.user_type === 'STUDENT';
+const route = useRoute();
+const currentTab = ref(
+  route.query.tab || (isStudent || popedom_code_list.includes(2000001) ? 'TaskList' : 'TemplateList')
+);
+
+function changeTab(tab) {
+  currentTab.value = tab;
+}
+provide('changeTab', changeTab);
+
+const tabList = {
+  TemplateList,
+  TaskList,
+  CurriculaListStudent,
+  CurriculaListTeacher
 };
+let currentTabComponent = computed(() => {
+  if (['TemplateList', 'TaskList'].includes(currentTab.value)) return tabList[currentTab.value];
+  return tabList[`${currentTab.value}${isStudent ? 'Student' : 'Teacher'}`];
+});
 </script>
 
 <style lang="scss" scoped>

+ 0 - 1
src/views/teacher/create_course/step_table/NewTask.vue

@@ -240,7 +240,6 @@ import { GetTaskTeachingTypeList, GetTaskModeList, GetTeacherListByCourseID, Get
 import { AddTaskToCSItem, GetTreeNodeInfo_BookChapterStruct, GetTaskInfo, UpdateTask, GetCSItem } from '@/api/course';
 import { fileUpload } from '@/api/app';
 import { fileTypeSizeLimit } from '@/utils/validate';
-import { taskModeList } from '@/store/data';
 
 import SelectCourse from '@/components/select/SelectCourse.vue';
 

+ 80 - 94
src/views/teacher/student_list/index.vue

@@ -26,7 +26,7 @@
         </div>
       </div>
       <div class="student-table">
-        <el-table :data="student_list">
+        <el-table :data="list">
           <el-table-column width="280">
             <template slot-scope="{ row }">
               <el-avatar icon="el-icon-user" size="small" :src="row.image_url" />
@@ -76,114 +76,100 @@
       @size-change="changePageSize"
     />
 
-    <send-message :visible.sync="visible" :title-name="titleName" @sendMessage="sendMessageToCourseStudent" />
+    <SendMessage :visible.sync="visible" :title-name="titleName" @sendMessage="sendMessageToCourseStudent" />
   </div>
 </template>
 
 <script>
+export default {
+  name: 'StudentList'
+};
+</script>
+
+<script setup>
+import { ref, inject } from 'vue';
 import { PageQueryCourseStudentList } from '@/api/list';
 import { AuditCourseStudent, SendMessageToCourseStudent } from '@/api/course';
+import { useList } from '@/utils/list';
+import { useRoute } from 'vue-router/composables';
+import { Loading, Message } from 'element-ui';
+
 import SendMessage from './SendMessage.vue';
 
-export default {
-  components: {
-    SendMessage
-  },
-  data() {
-    return {
-      course_id: this.$route.params.id,
-      student_name: '',
-      curTab: 'new',
-      visible: false,
-      titleName: '',
-      type: '',
-      student_id: '',
-      student_list: [],
-      page_capacity: 10,
-      cur_page: 1,
-      total_count: 0,
-      tabList: [
-        {
-          type: 'new',
-          name: 'Key298'
-        },
-        {
-          type: 'list',
-          name: 'Key296'
-        }
-      ]
-    };
-  },
-  created() {
-    this.queryCourseStudentList();
+const route = useRoute();
+
+let curTab = ref('new');
+const tabList = [
+  {
+    type: 'new',
+    name: 'Key298'
   },
-  methods: {
-    queryCourseStudentList() {
-      PageQueryCourseStudentList({
-        student_name: this.student_name,
-        course_id: this.course_id,
-        page_capacity: this.page_capacity,
-        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;
-      });
-    },
+  {
+    type: 'list',
+    name: 'Key296'
+  }
+];
 
-    changeTab(tab) {
-      this.student_list = [];
-      this.curTab = tab;
-      this.queryCourseStudentList();
-    },
+let { page_capacity, cur_page, total_count, list, changePage, changePageSize } = useList();
 
-    changePage(newPage) {
-      this.cur_page = newPage;
-      this.queryCourseStudentList();
-    },
+let course_id = ref(route.params.id);
+let student_name = ref('');
+function queryCourseStudentList() {
+  PageQueryCourseStudentList({
+    student_name: student_name.value,
+    course_id: course_id.value,
+    page_capacity: page_capacity.value,
+    cur_page: cur_page.value,
+    audit_status_list: curTab.value === 'new' ? [0] : [1]
+  }).then(({ student_list, total_count: total, cur_page: page }) => {
+    list.value = student_list;
+    total_count.value = total;
+    cur_page.value = page;
+  });
+}
+queryCourseStudentList();
 
-    changePageSize(pageSize) {
-      this.page_capacity = pageSize;
-      this.queryCourseStudentList();
-    },
+function changeTab(tab) {
+  list.value = [];
+  curTab.value = tab;
+  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;
-    },
+let type = ref('');
+let student_id = ref('');
+let visible = ref(false);
+let titleName = ref('');
+function sendMessage(types, studentId, student_name) {
+  type.value = types;
+  student_id.value = studentId;
+  titleName.value = type.value === 'all' ? '全部' : student_name;
+  visible.value = true;
+}
 
-    sendMessageToCourseStudent(content) {
-      const loading = this.$loading(this.$i18n.t('Key624'));
-      SendMessageToCourseStudent({
-        course_id: this.course_id,
-        content,
-        type: this.type,
-        student_id: this.student_id
-      })
-        .then(() => {
-          this.visible = false;
-          this.$message.success(this.$i18n.t('Key626'));
-        })
-        .finally(() => {
-          loading.close();
-        });
-    },
+const $t = inject('$t');
+function sendMessageToCourseStudent(content) {
+  const loading = Loading.service({ text: $t('Key624') });
+  SendMessageToCourseStudent({
+    course_id: course_id.value,
+    content,
+    type: type.value,
+    student_id: student_id.value
+  })
+    .then(() => {
+      visible.value = false;
+      Message.success($t('Key626'));
+    })
+    .finally(() => {
+      loading.close();
+    });
+}
 
-    auditCourseStudent(course_student_id, is_audited) {
-      AuditCourseStudent({ course_student_id, is_audited }).then(() => {
-        this.$message.success(this.$i18n.t('Key625'));
-        this.queryCourseStudentList();
-      });
-    }
-  }
-};
+function auditCourseStudent(course_student_id, is_audited) {
+  AuditCourseStudent({ course_student_id, is_audited }).then(() => {
+    Message.success($t('Key625'));
+    queryCourseStudentList();
+  });
+}
 </script>
 
 <style lang="scss" scoped>

+ 2 - 1
stylelint.config.js

@@ -48,6 +48,7 @@ module.exports = {
     'selector-class-pattern': null,
     'declaration-colon-newline-after': null,
     'value-keyword-case': ['lower', { camelCaseSvgKeywords: true }],
-    'value-no-vendor-prefix': [true, { ignoreValues: ['box'] }]
+    'value-no-vendor-prefix': [true, { ignoreValues: ['box'] }],
+    'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['deep'] }]
   }
 };

Vissa filer visades inte eftersom för många filer har ändrats