فهرست منبع

student pages

ChengYuXuan 5 سال پیش
والد
کامیت
f1b9f2d29f

+ 4 - 48
src/App.vue

@@ -1,57 +1,13 @@
 <template>
   <v-app>
-    <v-app-bar app color="primary" dark>
-      <div class="d-flex align-center">
-        <v-img
-          alt="Vuetify Logo"
-          class="shrink mr-2"
-          contain
-          src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
-          transition="scale-transition"
-          width="40"
-        />
-
-        <v-img
-          alt="Vuetify Name"
-          class="shrink mt-1 hidden-sm-and-down"
-          contain
-          min-width="100"
-          src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
-          width="100"
-        />
-      </div>
-
-      <v-spacer></v-spacer>
-
-      <v-btn
-        href="https://github.com/vuetifyjs/vuetify/releases/latest"
-        target="_blank"
-        text
-      >
-        <span class="mr-2">Latest Release</span>
-        <v-icon>mdi-open-in-new</v-icon>
-      </v-btn>
-    </v-app-bar>
-
-    <v-main>
-      <HelloWorld />
-    </v-main>
+    <router-view />
   </v-app>
 </template>
 
 <script lang="ts">
-import Vue from "vue";
-import HelloWorld from "./components/HelloWorld.vue";
+import Vue from 'vue'
 
 export default Vue.extend({
-  name: "App",
-
-  components: {
-    HelloWorld
-  },
-
-  data: () => ({
-    //
-  })
-});
+  name: 'App'
+})
 </script>

+ 58 - 0
src/components/PageHeader.vue

@@ -0,0 +1,58 @@
+<template>
+  <div class="pa-4">
+    <div v-if="title" class="d-flex">
+      <div class="flex-grow-1">
+        <h1 class="text-h3">{{ title }}</h1>
+        <v-breadcrumbs :items="breadcrumb" class="pl-0"></v-breadcrumbs>
+      </div>
+      <div class="flex-shrink-0">
+        <slot name="extra"></slot>
+      </div>
+    </div>
+
+    <v-subheader v-if="subtitle">{{ subtitle }}</v-subheader>
+    <v-tabs
+      v-if="tabs && tabs.length > 0"
+      background-color="transparent"
+      class="pb-4 ml-n4"
+    >
+      <v-tab
+        v-for="item in tabs"
+        :key="item.name"
+        :disabled="item.disabled"
+        :href="item.href"
+        :to="item.to"
+        >{{ item.name }}</v-tab
+      >
+    </v-tabs>
+
+    <slot></slot>
+  </div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue'
+export default Vue.extend({
+  name: 'PageHeader',
+  props: {
+    breadcrumb: {
+      type: Array,
+      default: () => []
+    },
+    title: {
+      type: String,
+      default: ''
+    },
+    subtitle: {
+      type: String,
+      default: ''
+    },
+    tabs: {
+      type: Array, // https://vuetifyjs.com/en/api/v-tab/#props
+      default: () => []
+    }
+  }
+})
+</script>
+
+<style scoped></style>

+ 3 - 0
src/mock/utils.js

@@ -0,0 +1,3 @@
+export default function randomArrayValue(arr = []) {
+  return Array.isArray(arr) ? arr[Math.floor(Math.random() * arr.length)] : ''
+}

+ 3 - 0
src/plugins/vuetify.config.ts

@@ -17,5 +17,8 @@ export const vuetifyConfig: Partial<UserVuetifyPreset> = {
         warning: '#FFCA28'
       }
     }
+  },
+  breakpoint: {
+    scrollBarWidth: 12
   }
 }

+ 39 - 0
src/router/student.ts

@@ -0,0 +1,39 @@
+import { RouteConfig } from 'vue-router'
+
+const routes: Array<RouteConfig> = [
+  {
+    meta: { roles: ['student'] },
+    path: '/student',
+    name: 'student',
+    component: () =>
+      import(
+        /* webpackChunkName: "student" */ '@/views/student/StudentHome.vue'
+      ),
+    redirect: 'student/home',
+    children: [
+      {
+        path: 'home',
+        name: 'home',
+        component: () =>
+          import(
+            /* webpackChunkName: "student" */ '@/views/student/Overview.vue'
+          )
+      },
+      {
+        path: 'info',
+        name: 'info',
+        component: () =>
+          import(/* webpackChunkName: "student" */ '@/views/student/Info.vue')
+      },
+      {
+        path: 'evalList',
+        name: 'evalList',
+        component: () =>
+          import(
+            /* webpackChunkName: "student" */ '@/views/student/EvalList.vue'
+          )
+      }
+    ]
+  }
+]
+export default routes

+ 26 - 10
src/views/Home.vue

@@ -1,18 +1,34 @@
 <template>
-  <div class="home">
-    <img alt="Vue logo" src="../assets/logo.png" />
-    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
-  </div>
+  <v-container>
+    <Login></Login>
+    <Register></Register>
+    <div>{{ mock }}</div>
+    <router-link :to="{ name: 'student' }">
+      <v-btn color="primary">student</v-btn>
+    </router-link>
+  </v-container>
 </template>
 
 <script lang="ts">
-import Vue from "vue";
-import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
-
+import Vue from 'vue'
+import Login from '@/views/portal/Login.vue'
+import Register from '@/views/portal/Register.vue'
+import { getEcho } from '@/api/exam.ts'
 export default Vue.extend({
-  name: "Home",
+  name: 'Home',
   components: {
-    HelloWorld
+    Login,
+    Register
+  },
+  data() {
+    return {
+      mock: ''
+    }
+  },
+  mounted() {
+    getEcho().then((res) => {
+      this.mock = res.data
+    })
   }
-});
+})
 </script>

+ 121 - 0
src/views/student/EvalList.vue

@@ -0,0 +1,121 @@
+<template>
+  <div>
+    <page-header title="我的评测" :breadcrumb="breadcrumb"> </page-header>
+    <v-row class="mr-16 ml-5 pa-0" no-gutters style="height: 50px">
+      <v-col>
+        <v-btn color="info" @click="onJoinExam">
+          参加评测
+        </v-btn>
+      </v-col>
+      <v-col cols="2">
+        <v-select
+          :items="selectItems"
+          outlined
+          v-model="selected"
+          dense
+        ></v-select>
+      </v-col>
+    </v-row>
+
+    <v-card
+      hover
+      v-for="item in examList"
+      :key="item.examName"
+      class="ma-5 mr-16 px-3"
+      style="cursor: default"
+    >
+      <v-row>
+        <v-col class="d-flex">
+          <v-card-title class="ma-0 pa-0">{{ item.examName }}</v-card-title>
+          <v-chip :color="item.state" label class="ml-5" outlined
+            >已结束</v-chip
+          >
+        </v-col>
+        <v-col align="end" class="mr-3">
+          <v-btn color="primary" class="mx-2">查看详情</v-btn>
+          <v-btn color="info" class="mx-2">参加评测</v-btn>
+        </v-col>
+      </v-row>
+      <v-row no-gutters align-content="start">
+        <v-col>
+          <v-card-text class="pa-0 pb-5">ID: {{ item.id }}</v-card-text>
+        </v-col>
+        <v-col>
+          <v-card-text class="pa-0 pb-5"
+            >开始时间: {{ item.startTime }}</v-card-text
+          >
+        </v-col>
+        <v-col>
+          <v-card-text class="pa-0 pb-5"
+            >结束时间: {{ item.endTime }}</v-card-text
+          >
+        </v-col>
+        <v-col>
+          <v-card-text class="pa-0 pb-5"
+            >邀请码: {{ item.inviteCode }}</v-card-text
+          >
+        </v-col>
+        <v-col>
+          <v-card-text class="pa-0 pb-5"
+            >参与人数: {{ item.participantsNumber }}</v-card-text
+          >
+        </v-col>
+      </v-row>
+    </v-card>
+    <v-pagination v-model="page" :length="pages"> </v-pagination>
+  </div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue'
+import PageHeader from '@/components/PageHeader.vue'
+import { getExamList } from '@/api/exam'
+
+export default Vue.extend({
+  name: 'ExamList',
+  components: {
+    PageHeader
+  },
+  data() {
+    return {
+      page: 1,
+      pages: 4,
+      selected: '正在进行',
+      selectItems: ['未开始', '正在进行', '已结束'],
+      dialog: false,
+      breadcrumb: [
+        {
+          text: '主页',
+          disabled: false,
+          href: '/'
+        },
+        {
+          text: '考试列表',
+          disabled: true,
+          href: '/'
+        }
+      ],
+      examList: []
+    }
+  },
+  methods: {
+    onJoinExam() {
+      console.log('参加评测')
+      this.$router.push('/exam/')
+    }
+  },
+  mounted() {
+    console.log('MOUNTED')
+    getExamList('myId')
+      .then((res) => {
+        console.log(res)
+        this.examList = res.data.data
+      })
+      .catch((err) => {
+        this.examList = []
+      })
+  }
+})
+</script>
+
+<style scoped></style>

+ 35 - 0
src/views/student/Info.vue

@@ -0,0 +1,35 @@
+<template>
+  <v-container>
+    <page-header title="Info" :breadcrumb="breadcrumb"></page-header>
+  </v-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue'
+import PageHeader from '@/components/PageHeader.vue'
+
+export default Vue.extend({
+  name: 'Info',
+  components: {
+    PageHeader
+  },
+  data() {
+    return {
+      breadcrumb: [
+        {
+          text: 'Home',
+          disabled: false,
+          href: '/'
+        },
+        {
+          text: 'Info',
+          disabled: true,
+          href: '/'
+        }
+      ]
+    }
+  }
+})
+</script>
+
+<style scoped></style>

+ 35 - 0
src/views/student/Overview.vue

@@ -0,0 +1,35 @@
+<template>
+  <v-container>
+    <page-header title="Overview" :breadcrumb="breadcrumb"></page-header>
+  </v-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue'
+import PageHeader from '@/components/PageHeader.vue'
+
+export default Vue.extend({
+  name: 'Overview',
+  components: {
+    PageHeader
+  },
+  data() {
+    return {
+      breadcrumb: [
+        {
+          text: 'Home',
+          disabled: false,
+          href: '/'
+        },
+        {
+          text: 'Overview',
+          disabled: true,
+          href: '/'
+        }
+      ]
+    }
+  }
+})
+</script>
+
+<style scoped></style>

+ 98 - 0
src/views/student/StudentHome.vue

@@ -0,0 +1,98 @@
+<template>
+  <v-app id="inspire">
+    <v-navigation-drawer app floating>
+      <div class="flex-column d-flex" style="height: 100vh">
+        <div class="flex-shrink-0">
+          <div class="pa-4">
+            <div
+              style="height: 40px; width: 100%"
+              class="indigo lighten-3 rounded-lg"
+            ></div>
+          </div>
+        </div>
+        <div class="overflow-auto flex-grow-1" style="box-sizing: border-box;">
+          <v-list nav dense>
+            <v-list-item-group v-model="selectedItem" color="primary">
+              <v-list-item
+                v-for="(item, i) in linkList"
+                :to="item.url"
+                :exact="item.exact"
+                :key="i"
+              >
+                <v-list-item-icon>
+                  <v-icon v-text="item.icon"></v-icon>
+                </v-list-item-icon>
+
+                <v-list-item-content>
+                  <v-list-item-title v-text="item.name"></v-list-item-title>
+                </v-list-item-content>
+              </v-list-item>
+            </v-list-item-group>
+          </v-list>
+        </div>
+        <div class="flex-shrink-0">
+          <div class="pa-2 pl-6 text--secondary">
+            <v-chip color="primary">Your Name ></v-chip>
+          </div>
+          <div class="pa-2 pl-6 pb-5 text--secondary">All Right Reserve</div>
+        </div>
+      </div>
+      <!--  -->
+    </v-navigation-drawer>
+
+    <v-main class="indigo lighten-5">
+      <router-view />
+    </v-main>
+  </v-app>
+</template>
+
+<script lang="ts">
+import Vue from 'vue'
+import {
+  mdiAccount,
+  mdiBell,
+  mdiViewList,
+  mdiTab,
+  mdiDetails,
+  mdiPackage,
+  mdiHome
+} from '@mdi/js'
+
+export default Vue.extend({
+  name: 'StudentHome',
+  components: {},
+  data: () => ({
+    icons: {
+      mdiAccount,
+      mdiBell
+    },
+    linkList: [
+      {
+        name: '首页',
+        url: '/student/home',
+        icon: mdiHome
+      },
+      {
+        name: '个人信息',
+        url: '/student/info',
+        icon: mdiAccount
+      },
+      {
+        name: '评测',
+        url: '/student/evalList',
+        icon: mdiViewList
+      },
+      {
+        name: '题目练习',
+        url: '/student/practice',
+        icon: mdiDetails
+      }
+    ]
+  }),
+  mounted() {
+    console.log('mount')
+  }
+})
+</script>
+
+<style scoped></style>