|
|
@@ -1,3 +1,249 @@
|
|
|
<template>
|
|
|
- <div></div>
|
|
|
+ <div>
|
|
|
+ <page-header :routes="[{ name: '我的小组' }]">
|
|
|
+ <template slot="title">
|
|
|
+ 我的小组 {{ this.groups.length > 0 && `「${this.groups[0].name}」` }}
|
|
|
+ </template>
|
|
|
+ </page-header>
|
|
|
+ <page-body>
|
|
|
+ <div v-if="groups.length > 0">
|
|
|
+ <div class="page-section">
|
|
|
+ <div class="columns is-desktop">
|
|
|
+ <div class="column">
|
|
|
+ <h5 class="title is-5">id:</h5>
|
|
|
+ <div class="subtitle is-6">{{ groups[0].id }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="column">
|
|
|
+ <h5 class="title is-5">名称:</h5>
|
|
|
+ <div class="subtitle is-6">{{ groups[0].name }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="column">
|
|
|
+ <h5 class="title is-5">选组码:</h5>
|
|
|
+ <div class="subtitle is-6">{{ groups[0].code }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="divider">
|
|
|
+ <div class="columns is-multiline is-desktop">
|
|
|
+ <div
|
|
|
+ class="column is-3"
|
|
|
+ :key="member.id"
|
|
|
+ v-for="member in groups[0].members"
|
|
|
+ >
|
|
|
+ <card>
|
|
|
+ <h5 class="title is-5">成员:「{{ member.nickname }}」</h5>
|
|
|
+ <div class="subtitle is-6">{{ member.username }}</div>
|
|
|
+ </card>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-if="!isLoadingGroup && groups.length === 0"
|
|
|
+ style="padding: 50px"
|
|
|
+ class="columns is-desktop is-vcentered"
|
|
|
+ >
|
|
|
+ <div class="column is-three-fifths-desktop">
|
|
|
+ <img src="@/assets/undraw_having_fun.svg" alt="" />
|
|
|
+ </div>
|
|
|
+ <div class="column">
|
|
|
+ <div class="title is-spaced">您还尚未加入任何小组</div>
|
|
|
+ <p class="subtitle">加入或创建小组,一起迎接挑战!</p>
|
|
|
+ <div class="buttons">
|
|
|
+ <a
|
|
|
+ @click="() => (this.showCreateModal = true)"
|
|
|
+ class="button is-primary"
|
|
|
+ >创建小组
|
|
|
+ </a>
|
|
|
+ <a
|
|
|
+ @click="() => (this.showJoinModal = true)"
|
|
|
+ class="button is-primary is-outlined"
|
|
|
+ >加入小组
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </page-body>
|
|
|
+ <b-modal :active.sync="showCreateModal" :width="400">
|
|
|
+ <div class="card">
|
|
|
+ <div class="title">创建小组</div>
|
|
|
+ <b-notification type="is-danger" :active.sync="isServerError">
|
|
|
+ {{ errorMassage }}
|
|
|
+ </b-notification>
|
|
|
+ <div class="content">
|
|
|
+ <b-field
|
|
|
+ label="名称"
|
|
|
+ :type="$v.name.$error ? 'is-danger' : ''"
|
|
|
+ :message="
|
|
|
+ $v.name.$error
|
|
|
+ ? [
|
|
|
+ !$v.name.basicChar
|
|
|
+ ? '名称只能由大小写字母,数字,- 与 _ 组成'
|
|
|
+ : undefined,
|
|
|
+ !$v.name.required ? '请输入名称' : undefined
|
|
|
+ ]
|
|
|
+ : ''
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <b-input maxlength="50" v-model="$v.name.$model"></b-input>
|
|
|
+ </b-field>
|
|
|
+
|
|
|
+ <a
|
|
|
+ class="button is-primary"
|
|
|
+ :class="{ 'is-loading': submitLoading }"
|
|
|
+ @click="createGroup()"
|
|
|
+ >
|
|
|
+ 创建小组
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </b-modal>
|
|
|
+ <b-modal :active.sync="showJoinModal" :width="400">
|
|
|
+ <div class="card">
|
|
|
+ <div class="title">加入小组</div>
|
|
|
+ <b-notification type="is-danger" :active.sync="isServerError">
|
|
|
+ {{ errorMassage }}
|
|
|
+ </b-notification>
|
|
|
+ <div class="content">
|
|
|
+ <b-field
|
|
|
+ label="选组码"
|
|
|
+ :type="$v.code.$error ? 'is-danger' : ''"
|
|
|
+ :message="
|
|
|
+ $v.name.$error
|
|
|
+ ? [!$v.code.required ? '请输入选组码' : undefined]
|
|
|
+ : ''
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <b-input v-model="$v.code.$model"></b-input>
|
|
|
+ </b-field>
|
|
|
+ <a
|
|
|
+ class="button is-primary"
|
|
|
+ :class="{ 'is-loading': submitLoading }"
|
|
|
+ @click="joinGroup()"
|
|
|
+ >
|
|
|
+ 申请加入小组
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </b-modal>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
+<script>
|
|
|
+import PageHeader from "@/components/PageHeader";
|
|
|
+import PageBody from "@/components/PageBody/index";
|
|
|
+import Card from "@/components/Card";
|
|
|
+import { required } from "vuelidate/lib/validators";
|
|
|
+import {
|
|
|
+ getStudentGroup,
|
|
|
+ postStudentGroup,
|
|
|
+ putStudentGroup
|
|
|
+} from "@/api/group";
|
|
|
+export default {
|
|
|
+ components: { PageBody, PageHeader, Card },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ showCreateModal: false,
|
|
|
+ showJoinModal: false,
|
|
|
+ name: "",
|
|
|
+ code: "",
|
|
|
+ isServerError: false,
|
|
|
+ errorMassage: "",
|
|
|
+ submitLoading: false,
|
|
|
+ isLoadingGroup: false,
|
|
|
+ groups: []
|
|
|
+ };
|
|
|
+ },
|
|
|
+ validations: {
|
|
|
+ name: {
|
|
|
+ required,
|
|
|
+ basicChar: name => /^[a-zA-Z0-9_-]*$/.test(name)
|
|
|
+ },
|
|
|
+ code: {
|
|
|
+ required
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ showCreateModal(newValue) {
|
|
|
+ if (newValue === false) {
|
|
|
+ this.onModalClosed();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ showJoinModal(newValue) {
|
|
|
+ if (newValue === false) {
|
|
|
+ this.onModalClosed();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.loadGroup();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async createGroup() {
|
|
|
+ this.$v.$touch();
|
|
|
+ if (!this.$v.name.$invalid) {
|
|
|
+ try {
|
|
|
+ this.submitLoading = true;
|
|
|
+ this.isServerError = false;
|
|
|
+ await postStudentGroup(this.name);
|
|
|
+ this.$toast.open({
|
|
|
+ message: `小组「${this.name}」创建成功`,
|
|
|
+ type: "is-success"
|
|
|
+ });
|
|
|
+ this.showCreateModal = false;
|
|
|
+ this.loadGroup();
|
|
|
+ } catch (e) {
|
|
|
+ this.errorMassage = e.message;
|
|
|
+ this.isServerError = true;
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async joinGroup() {
|
|
|
+ this.$v.$touch();
|
|
|
+ if (!this.$v.code.$invalid) {
|
|
|
+ try {
|
|
|
+ this.submitLoading = true;
|
|
|
+ this.isServerError = false;
|
|
|
+ await putStudentGroup(this.code);
|
|
|
+ this.$toast.open({
|
|
|
+ message: `小组加入成功`,
|
|
|
+ type: "is-success"
|
|
|
+ });
|
|
|
+ this.showJoinModal = false;
|
|
|
+ this.loadGroup();
|
|
|
+ } catch (e) {
|
|
|
+ this.errorMassage = e.message;
|
|
|
+ this.isServerError = true;
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onModalClosed() {
|
|
|
+ this.isServerError = false;
|
|
|
+ this.submitLoading = false;
|
|
|
+ },
|
|
|
+ async loadGroup() {
|
|
|
+ this.isLoadingGroup = true;
|
|
|
+ const { courseId } = this.$route.params;
|
|
|
+ const { data } = await getStudentGroup(courseId);
|
|
|
+ this.groups = data;
|
|
|
+ this.isLoadingGroup = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+@import "../../../assets/scss/app";
|
|
|
+.card {
|
|
|
+ padding: $default-margin-between;
|
|
|
+ border-radius: $default-radius;
|
|
|
+}
|
|
|
+
|
|
|
+.divider {
|
|
|
+ padding-top: $default-margin-between;
|
|
|
+}
|
|
|
+</style>
|