qiyunfeng-create
2 天以前 5f00696dfb25bc90034448ceb634ed1ef256681a
src/views/personalCenter/class.vue
@@ -1,7 +1,462 @@
<template>
  <div class="myBook">
    <div class="myBook_header">
      <div class="myBook_header_title">我的班级</div>
  <div class="coursePage">
    <div class="personalPage-title">我的班级</div>
    <div class="tabs">
      <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
        <el-tab-pane
          :label="'当前班级(' + calssList.length + ')'"
          name="1"
        ></el-tab-pane>
        <!-- <el-tab-pane label="历史班级(5)" name="2"></el-tab-pane> -->
      </el-tabs>
    </div>
    <div class="headerBox">
      <div class="searchBox">
        <el-input
          v-model="searchKey"
          clearable
          @clear="searchList()"
          placeholder="请输入关键字"
        >
          <template #append>
            <el-button
              type="primary"
              class="searchBtn"
              @click="searchList()"
              :icon="Search"
            />
          </template>
        </el-input>
      </div>
      <el-button type="primary" class="applyStartClasses" @click="openJoin()"
        >加入班级</el-button
      >
      <el-dialog v-model="dialogVisible" title="加入班级" width="500">
        <div class="codeContent">
          <span>邀请码:</span>
          <el-input style="width: 330px" v-model="codeText" placeholder="请输入邀请码" />
          <el-button type="primary" @click="getClassDetail">确认</el-button>
        </div>
        <div class="classInfo" v-if="classDetail?.name">
          <div class="itemCon">
            <span>班级名称:</span>
            <span>{{ classDetail.name }}</span>
          </div>
          <div class="itemCon">
            <span>班级人数:</span>
            <span>{{ classDetail.memberCount }} / {{ classDetail.maxUserCount }}</span>
          </div>
          <div class="itemCon">
            <span>开课时间:</span>
            <span
              >{{ moment(classDetail.beginDate).format("YYYY-MM-DD") }} -
              {{ moment(classDetail.endDate).format("YYYY-MM-DD") }}</span
            >
          </div>
        </div>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="dialogVisible = false"> 取消 </el-button>
            <el-button type="primary" @click="joinClass()"> 确认 </el-button>
          </div>
        </template>
      </el-dialog>
    </div>
    <div class="courseListBox" v-if="calssList.length > 0 && !isLoading">
      <div class="courseItem" v-for="(item, index) in calssList" :key="index">
        <div class="itemHeader">
          <div class="title">{{ item.name }}</div>
          <div class="courseId">(ID:{{ item.id }})</div>
          <!-- <div class="copyIdBtn" @click="copy(item.refCode)">复制邀请码</div> -->
        </div>
        <div class="itemInfo" @click="goClassManage(item)">
          <div class="infoBox">
            <p>
              状态:<span v-if="item.userState == 'WaitValid'" style="color: #ef9f29">
                审核中 </span
              ><span v-if="item.userState == 'Normal'" style="color: #1dbd11">
                进行中 </span
              ><span v-if="item.userState == 'Reject'" style="color: red"> 未通过 </span>
            </p>
            <p>班级人数:{{ item.memberCount }} / {{ item.maxUserCount }}</p>
            <p>有效期:{{ item.classTime }}</p>
          </div>
        </div>
      </div>
    </div>
    <el-empty description="暂无数据" v-if="calssList.length == 0 && !isLoading" />
    <div style="min-height: 200px" v-if="isLoading" v-loading="isLoading"></div>
    <div class="pageBox">
      <el-pagination
        v-model:current-page="pages.currentPage"
        :page-size="pages.pageSize"
        :size="'small'"
        :disabled="pages.count <= 1"
        layout="total, prev, pager, next"
        :total="pages.count"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted, inject, watch } from "vue";
import { Search } from "@element-plus/icons-vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { getPublicImage } from "@/assets/js/middleGround/tool.js";
import moment from "moment";
import useClipboard from "vue-clipboard3";
const { toClipboard } = useClipboard();
const MG: any = inject("MG");
const config: any = inject("config");
const router = useRouter();
const activeName = ref("1");
interface ClassItem {
  id: string;
  name: string;
  memberCount: number;
  maxUserCount: number;
  userState: string;
  beginDate: string;
  endDate: string;
  classTime: string;
  linkProductDto: {
    product: {
      name: string;
      icon: string;
    };
  };
}
const calssList = ref<ClassItem[]>([]);
const searchKey = ref("");
const codeText = ref("");
const dialogVisible = ref(false);
const classDetail = ref();
const isLoading = ref(true);
let pages = reactive({
  currentPage: 1,
  page: 1,
  pageSize: 6,
  count: 0,
  loading: false,
});
onMounted(() => {
  getCurrentClassList();
});
//  分页
const handleSizeChange = (val: number) => {
  pages.pageSize = val;
  getCurrentClassList();
};
const handleCurrentChange = (val: number) => {
  pages.page = val;
  pages.currentPage = val;
  getCurrentClassList();
};
const handleClick = (val: any) => {
  activeName.value = val;
};
const openJoin = () => {
  dialogVisible.value = true;
  classDetail.value = null;
  codeText.value = "";
};
// 搜索
const searchList = () => {
  pages.page = 1;
  pages.currentPage = 1;
  getCurrentClassList();
};
// 复制
const copy = async (text: string) => {
  try {
    await toClipboard(text);
    ElMessage({
      message: "复制成功",
      type: "success",
    });
  } catch (e) {
    console.error(e);
  }
};
// 加入班级
const joinClass = () => {
  if (!codeText.value) {
    ElMessage({
      message: "无效的邀请码",
      type: "error",
    });
    return false;
  }
  const data = { refCode: codeText.value };
  MG.identity.joinGroupByRefCode(data).then((res: any) => {
    if (res == "组不存在") {
      ElMessage({
        message: "无效的班级",
        type: "error",
      });
    }
    if (res == "组成员数量已最大,不能加入") {
      ElMessage({
        message: "班级成员数量已最大,不能加入",
        type: "error",
      });
    }
    if (res == "已经申请过加入此组") {
      ElMessage({
        message: "已经申请过加入此班级",
        type: "error",
      });
    }
    dialogVisible.value = false;
    getCurrentClassList();
  });
};
// 获取当前班级列表
const getCurrentClassList = () => {
  isLoading.value = true;
  const data = {
    start: (pages.page - 1) * pages.pageSize,
    size: pages.pageSize,
    sort: {
      type: "Desc",
      field: "CreateDate",
      subSorts: [],
    },
    filterList: [],
    searchList: searchKey.value
      ? [
          {
            keywords: searchKey.value,
            field: "Name",
            compareType: "Contains",
          },
        ]
      : [],
  };
  MG.identity.joinedGroupByList(data).then((res: any) => {
    isLoading.value = false;
    pages.count = res.totalSize;
    if (res.datas) {
      calssList.value = res.datas.map((item: any) => {
        return {
          ...item,
          classTime:
            moment(item.beginDate).format("YYYY.MM.DD") +
            "--" +
            moment(item.endDate).format("YYYY.MM.DD"),
          bookName: item.linkProductDto.product.name,
          bookIcon: getPublicImage(item.linkProductDto.product.icon, 100),
        };
      });
    }
  });
};
// 跳转班级管理
const goClassManage = async (item: any) => {
  if (item.userState == "WaitValid") {
    ElMessage({
      message: "正在审核中....",
      type: "warning",
    });
    return false;
  }
  if (item.userState == "Reject") {
    ElMessage({
      message: "审核未通过",
      type: "warning",
    });
    return false;
  }
  const bookInfo = await getBookDetail(item.linkProductDto?.product);
  let info = {
    id: item.id,
    name: item.name,
    icon: bookInfo.icon,
    rootCmsItemId: bookInfo.rootCmsItemId,
    bookId: bookInfo.id,
    author: bookInfo.author,
    isbn: bookInfo.isbn,
    bookRefCode: bookInfo.refCode,
  };
  let page = router.resolve({
    path: "/classManage",
    query: {
      classInfo: JSON.stringify(info),
    },
  });
  window.open(page.href, "_blank");
  // router.push({
  //   path: '/classManage',
  //   query: {
  //     classInfo: JSON.stringify(info)
  //   }
  // })
};
// 获取教材详情
const getBookDetail = async (item: any) => {
  const path = item.refCode ? "jsek_digitalTextbooks" : config.goodsStore;
  let query = {
    path,
    queryType: "*",
    productId: String(item.id),
    storeInfo: path,
    coverSize: {
      height: 300,
      width: 210,
    },
    fields: {
      author: [],
      isbn: [],
    },
  };
  const res = await MG.store.getProductDetail(query);
  return res.datas ?? null;
};
// 通过code查询班级
const getClassDetail = () => {
  if (codeText.value == "") {
    ElMessage({
      message: "请输入邀请码",
      type: "warning",
    });
    return false;
  }
  const data = {
    classIdOrRefCode: codeText.value,
  };
  MG.edu
    .getCourseClass(data)
    .then((res: any) => {
      classDetail.value = res;
    })
    .catch((err: any) => {
      console.log(err);
    });
};
</script>
<style lang="less" scoped>
.coursePage {
  .tabs {
    padding: 0 20px;
  }
  .headerBox {
    padding: 5px 20px;
    margin-bottom: 10px;
    overflow: hidden;
    .searchBox {
      width: 300px;
      float: left;
      .searchBtn {
        background-color: var(--el-color-primary);
        color: #fff;
        border-top-left-radius: 0;
        border-bottom-left-radius: 0;
      }
    }
    .applyStartClasses {
      float: right;
    }
  }
  .courseListBox {
    overflow: hidden;
    .courseItem {
      float: left;
      width: 46%;
      margin: 0 2% 20px;
      border-radius: 8px;
      border: 1px solid #efefef;
      overflow: hidden;
      .itemHeader {
        height: 40px;
        line-height: 40px;
        padding: 0 20px;
        // color: #fff;
        background-color: #f8f8f8;
        .title {
          font-weight: 600;
        }
        div {
          display: inline-block;
        }
        .courseId {
          margin-left: 6px;
          font-size: 12px;
          color: #999;
        }
        .copyIdBtn {
          float: right;
          height: 20px;
          line-height: 20px;
          margin-top: 10px;
          font-size: 12px;
          background-color: #fff;
          color: #3b93fe;
          padding: 0 6px;
          border-radius: 50px;
          overflow: hidden;
          cursor: pointer;
        }
      }
      .itemInfo {
        padding: 20px;
        flex: 1;
        display: flex;
        cursor: pointer;
        .imgBox {
          width: 90px;
          height: 120px;
          margin-right: 20px;
        }
        .infoBox {
          flex: 1;
          font-size: 12px;
          p {
            margin-bottom: 10px;
          }
        }
      }
    }
  }
  .codeContent {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 30px;
  }
  .classInfo {
    padding: 30px 0;
    border-top: 2px dashed #ccc;
    .itemCon {
      margin-bottom: 20px;
    }
  }
  .pageBox {
    padding: 10px 0;
    display: flex;
    justify-content: center;
  }
}
</style>