18 Commits 8f27c8f994 ... d16fcc98d7

Autor SHA1 Mensagem Data
  Prevalence d16fcc98d7 老师端的界面初步进行 7 anos atrás
  Prevalence d4036086f7 Merge remote-tracking branch 'origin/master' into feature/dlwork 7 anos atrás
  ZhouWeilu 941e89077f Merge branch 'hotfix/zhouweilu' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into master 7 anos atrás
  soleil 7109ba8812 [修改]昵称改为学号 7 anos atrás
  WuXinyu a47b76e16d Merge branch 'develop' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into master 7 anos atrás
  WuXinyu 30f8191bcb Merge branch 'hotfix/bay' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into develop 7 anos atrás
  Kunduin 9e5ba0a240 [FIX] merge 7 anos atrás
  Kunduin dc04a2afcd [IMPROVE] 更新时间输入format 7 anos atrás
  Kunduin 234ebe42d3 [IMPROVE] 更新时间输入format 7 anos atrás
  WuXinyu d7b8b34db4 Merge branch 'develop' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into master 7 anos atrás
  WuXinyu f15e54629d Merge branch 'hotfix/bay' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into develop 7 anos atrás
  Kunduin 659a772ae3 [IMPROVE] 移除测试依赖 7 anos atrás
  ZhouWeilu 7decc7a42e Merge branch 'hotfix/zhouweilu' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into master 7 anos atrás
  soleil 5ec31844e6 [修改]测试标签状态,开始部署日志获取bug 7 anos atrás
  soleil 1e4dcc5cf3 [修改] 7 anos atrás
  ZhouWeilu 8de5dcb026 Merge branch 'hotfix/zhouweilu' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into master 7 anos atrás
  soleil 848dbb6d33 [修改]创建代码作业逻辑 7 anos atrás
  soleil e4380daa85 Merge branch 'hotfix/zhouweilu' into develop 7 anos atrás

+ 0 - 4
package.json

@@ -34,13 +34,10 @@
     "@pollyjs/persister-fs": "^1.4.1",
     "@pollyjs/persister-local-storage": "^1.4.1",
     "@vue/cli-plugin-babel": "^3.2.0",
-    "@vue/cli-plugin-e2e-nightwatch": "^3.2.0",
     "@vue/cli-plugin-eslint": "^3.2.0",
     "@vue/cli-plugin-pwa": "^3.2.0",
-    "@vue/cli-plugin-unit-jest": "^3.2.0",
     "@vue/cli-service": "^3.2.0",
     "@vue/eslint-config-prettier": "^4.0.0",
-    "@vue/test-utils": "^1.0.0-beta.20",
     "babel-core": "7.0.0-bridge.0",
     "babel-eslint": "^10.0.1",
     "babel-jest": "^23.6.0",
@@ -52,7 +49,6 @@
     "lint-staged": "^7.2.2",
     "node-sass": "^4.9.0",
     "sass-loader": "^7.0.1",
-    "setup-polly-jest": "^0.5.2",
     "vue-cli-plugin-buefy": "^0.3.3",
     "vue-template-compiler": "^2.5.17",
     "winston": "^3.1.0"

+ 8 - 0
src/api/dlwork.js

@@ -11,6 +11,14 @@ import { DL_WORK_MODULE } from "./_prefix";
 export const getDLAssignmentListByStu = courseId => {
   return request(`${DL_WORK_MODULE}/student/course/${courseId}/dlwork`);
 };
+/**
+ * 老师查看机器学习作业列表
+ * @param courseId
+ * @returns {Promise<*>}
+ */
+export const getDLAssignmentListByTeacher = courseId => {
+  return request(`${DL_WORK_MODULE}/teacher/course/${courseId}/dlwork`);
+};
 /**
  * 获得Project的详细信息
  * @param dlworkId

+ 30 - 22
src/components/AssignmentCRUD/CreateAssignment/index.vue

@@ -232,7 +232,6 @@ export default {
       errorMassage: null,
       isServerError: false,
       submitting: false,
-
       // 转圈圈
       loadingSearchQuestions: false,
       loadingCreateAssignment: false
@@ -318,30 +317,39 @@ export default {
           // 代码作业
           this.myPromise = postCodeAssignment(param, this.courseId);
         }
-        this.myPromise.then(res => {
-          //创建成功
-          this.isCreateModalActive = false;
-          if (res.code === 0) {
-            if (this.assignType === 1) {
-              this.$router.push({
-                path: `${this.prefix}/review?documentHwId=${res.data.id}`
+        this.myPromise
+          .then(res => {
+            //创建成功
+            this.isCreateModalActive = false;
+            this.submitting = false;
+            if (res.code === 0) {
+              if (this.assignType === 1) {
+                this.$router.push({
+                  path: `${this.prefix}/review?documentHwId=${res.data.id}`
+                });
+              }
+              this.$emit("sendCreatedAssignment", res.data);
+              this.loadingCreateAssignment = false;
+            } else {
+              //创建失败
+              this.isCreateModalActive = false;
+              this.loadingCreateAssignment = false;
+
+              this.$dialog.alert({
+                title: "创建失败",
+                message: res.message,
+                type: "is-danger",
+                hasIcon: true
               });
             }
-            this.$emit("sendCreatedAssignment", res.data);
-            this.loadingCreateAssignment = false;
-          } else {
-            //创建失败
-            this.isCreateModalActive = false;
-            this.loadingCreateAssignment = false;
-            this.$dialog.alert({
-              title: "创建失败",
-              message: res.message,
-              type: "is-danger",
-              hasIcon: true
+          })
+          .catch(e => {
+            this.submitting = false;
+            this.$toast.open({
+              message: e.message || "服务器未知错误",
+              type: "is-danger"
             });
-          }
-        });
-        this.submitting = false;
+          });
       }
     },
     getDifficultyType(level) {

+ 5 - 0
src/layouts/courseLayouts/TeacherMenu.vue

@@ -25,6 +25,11 @@
           <img alt="" src="../../assets/icon/laptop.png" />代码作业
         </router-link>
       </li>
+      <li>
+        <router-link active-class="is-active" :to="`${prefix}/dlwork`">
+          <img alt="" src="../../assets/icon/laptop.png" />机器学习作业
+        </router-link>
+      </li>
       <li>
         <router-link active-class="is-active" :to="`${prefix}/document`">
           <img alt="" src="../../assets/icon/file.png" />文档作业

+ 1 - 1
src/mixins/time.js

@@ -11,7 +11,7 @@ export default {
       return {
         enableTime: true,
         dateFormat: "U",
-        altFormat: "M	j, Y  H:i",
+        altFormat: "Y年n月J h:i K",
         altInput: true,
         locale: Mandarin
       };

+ 4 - 0
src/router/routes.js

@@ -76,6 +76,10 @@ export default [
         path: "result",
         component: () => import("@/views/teacher/Result")
       },
+      {
+        path: "dlwork",
+        component: () => import("@/views/teacher/DlWork/index")
+      },
       {
         path: "code",
         component: () => import("@/views/teacher/Code/index")

+ 2 - 2
src/views/login/Register.vue

@@ -5,13 +5,13 @@
       {{ errorMassage }}
     </b-notification>
     <b-field
-      label="昵称"
+      label="学号"
       :type="$v.nickname.$error ? 'is-danger' : ''"
       :message="$v.nickname.$error ? '昵称须由长度为4至16的字母或数字组成' : ''"
     >
       <b-input
         v-model="$v.nickname.$model"
-        placeholder="在此输入昵称"
+        placeholder="在此输入学号"
       ></b-input>
     </b-field>
     <b-field

+ 8 - 13
src/views/student/Code/ProjectDetail/DeployDetail.vue

@@ -37,7 +37,7 @@
         </div>
       </div>
       <button
-        :class="['button', 'block', 'is-link', { 'is-loading': isRunning }]"
+        :class="['button', 'block', 'is-link', { 'is-loading': isRunning || deployButtonDisabled }]"
         @click="startDeploy"
         style="margin-top: 20px;"
       >
@@ -116,7 +116,8 @@ export default {
       latestMirrorIdList: [],
       radio: -1,
       isfetchLog: false,
-      latestDeployId: 0
+      latestDeployId: 0,
+      deployButtonDisabled: false
     };
   },
   props: {
@@ -131,13 +132,6 @@ export default {
   },
   watch: {
     projectDetail: function() {
-      // console.log(newVal);
-      //获取最新一次部署详细信息
-      // if (newVal.latestDeploy && newVal.latestDeploy.id) {
-      //   // this.haveDeployRecord = true;
-      //
-      //   // this.getDeployLogInfo(this.projectDetail.latestDeploy.id);
-      // }
       this.getLatestDeployInfo();
       this.getLatestBuildInfo(this.projectDetail && this.projectDetail.id, 5);
       this.getLastNDeployInfoList(
@@ -199,11 +193,13 @@ export default {
     },
     //开始部署
     startDeploy() {
+      this.deployButtonDisabled = true;
       if (this.radio == -1) {
         this.$toast.open({
           message: "请先选择镜像",
           type: "is-danger"
         });
+        this.deployButtonDisabled = false;
         return;
       } else {
         let mirrorId = this.getSelectedMirrorId();
@@ -214,6 +210,7 @@ export default {
           replicas: 1
         })
           .then(res => {
+            this.deployButtonDisabled = false;
             if (res.data.status == "SUCCESS") {
               this.$toast.open({
                 message: "不要重复部署哦~",
@@ -221,18 +218,16 @@ export default {
               });
               return;
             }
-            // console.log(res);
             this.$toast.open({
               message: "开始部署",
               type: "is-success"
             });
             this.isRunning = true;
             this.deployInfo = res.data;
-            // setTimeout(() => {
-            //   this.getLatestDeployInfo(this.projectDetail.latestDeploy.id);
-            // }, 1000);
+            this.latestDeployId = res.data.id;
           })
           .catch(e => {
+            this.deployButtonDisabled = false;
             this.$toast.open({
               message: e.message || "服务器未知错误",
               type: "is-danger"

+ 2 - 1
src/views/student/Code/ProjectDetail/Test/FunctionalTestDetail.vue

@@ -18,7 +18,8 @@
         页面测试 #{{ testDetail.id }}
       </template>
       <template slot="content">
-        <pass-tag :pass="testDetail.passAll" />
+        <pass-tag v-if="testDetail.status == 1" :pass="testDetail.passAll" />
+        <b-tag v-else type="is-warning">RUNNING</b-tag>
       </template>
       <template slot="extraContent">
         <div class="tag">{{ displayUnixTime(testDetail.time) }}</div>

+ 10 - 2
src/views/student/Code/ProjectDetail/Test/UnitTestDetail.vue

@@ -18,7 +18,8 @@
         单元测试 #{{ testDetail.id }}
       </template>
       <template slot="content">
-        <pass-tag :pass="testDetail.passAll" />
+        <pass-tag v-if="testDetail.status == 1" :pass="testDetail.passAll" />
+        <b-tag v-else type="is-warning">RUNNING</b-tag>
       </template>
       <template slot="extraContent">
         <div class="tag">{{ displayUnixTime(testDetail.time) }}</div>
@@ -69,8 +70,15 @@ import { getUnitTestDetail } from "@/api/codehw";
 import timeMixins from "@/mixins/time";
 import PassTag from "@/views/student/Code/ProjectDetail/components/PassTag";
 import PageSectionLoading from "@/components/PageBody/PageSectionLoading/index";
+import BTag from "buefy/src/components/tag/Tag";
 export default {
-  components: { PageSectionLoading, PassTag, PageBody, PageHeader },
+  components: {
+    BTag,
+    PageSectionLoading,
+    PassTag,
+    PageBody,
+    PageHeader
+  },
   data() {
     return {
       testDetail: { detail: [] },

+ 4 - 0
src/views/student/Code/ProjectDetail/TestDetail.vue

@@ -16,6 +16,7 @@
         >
           <div><strong>UNIT TEST : #</strong> {{ item.id }}</div>
           <pass-tag v-if="item.status == 1" :pass="item.passAll" />
+          <b-tag v-else type="is-warning">RUNNING</b-tag>
           <span style="padding-left: 10px">{{
             displayUnixTime(item.time)
           }}</span>
@@ -53,6 +54,7 @@
         >
           <div><strong>FUNCTIONAL TEST : #</strong> {{ item.id }}</div>
           <pass-tag v-if="item.status == 1" :pass="item.passAll" />
+          <b-tag v-else type="is-warning">RUNNING</b-tag>
           <span style="padding-left: 10px">{{
             displayUnixTime(item.time)
           }}</span>
@@ -67,9 +69,11 @@ import PassTag from "@/views/student/Code/ProjectDetail/components/PassTag";
 import timeMixins from "@/mixins/time";
 import { makeFunctionalTest } from "@/api/codehw";
 import PageSectionLoading from "@/components/PageBody/PageSectionLoading/index";
+import BTag from "buefy/src/components/tag/Tag";
 
 export default {
   components: {
+    BTag,
     PageSectionLoading,
     PassTag
   },

+ 176 - 0
src/views/teacher/DlWork/index.vue

@@ -0,0 +1,176 @@
+<template>
+  <div>
+    <page-header
+      :loading="loadingDlWorkList"
+      :routes="[{ name: '机器学习作业', path: 'dlwork' }]"
+    >
+      <template slot="title">
+        机器学习作业列表
+      </template>
+      <template slot="content">
+        共有 {{ dlworkData.length }} 份作业
+      </template>
+      <template slot="action">
+        <create-assignment
+          @sendCreatedAssignment="pushNewAssignment($event)"
+          :course-id="Number(course.id)"
+          :assign-type="assignType"
+        ></create-assignment>
+      </template>
+    </page-header>
+
+    <page-body>
+      <page-section-loading :show="loadingDlWorkList" />
+      <div class="data-table">
+        <b-table
+          v-if="!loadingDlWorkList"
+          :data="dlworkData"
+          detailed
+          detail-key="id"
+        >
+          <template slot-scope="props">
+            <b-table-column label="作业名称" centered>
+              <router-link
+                :to="{
+                  path: `code/${props.row.id}`
+                }"
+              >
+                {{ props.row.name }}
+              </router-link>
+            </b-table-column>
+            <b-table-column label="状态" centered>
+              {{ props.row.status }}
+            </b-table-column>
+
+            <b-table-column label="开始时间" centered>
+              {{ displayUnixTime(props.row.startAt) }}
+            </b-table-column>
+
+            <b-table-column label="结束时间" centered>
+              {{ displayUnixTime(props.row.endAt) }}
+            </b-table-column>
+            <b-table-column label="修改" centered>
+              <update-assignment
+                :assign-type="assignType"
+                :update-item="props.row"
+                @updateDocData="updateData($event)"
+              ></update-assignment>
+            </b-table-column>
+            <b-table-column label="删除" centered>
+              <delete-assignment
+                :del-id="props.row.id"
+                :assign-type="assignType"
+                @del="deleteAssignment(props.row.id)"
+              ></delete-assignment>
+            </b-table-column>
+          </template>
+
+          <template slot="detail" slot-scope="props">
+            <article class="media">
+              <div class="media-content">
+                <div class="content">
+                  <p>
+                    <strong>作业描述:</strong>
+                    <small>{{ props.row.description }}</small> <br />
+                  </p>
+                </div>
+              </div>
+            </article>
+          </template>
+        </b-table>
+        <no-data-svg
+          style="margin-top: 20px;"
+          v-if="!loadingDlWorkList && !(dlworkData && dlworkData.length > 0)"
+        ></no-data-svg>
+      </div>
+    </page-body>
+  </div>
+</template>
+
+<script>
+import PageHeader from "@/components/PageHeader";
+import PageBody from "@/components/PageBody/index";
+import { getDLAssignmentListByTeacher } from "@/api/dlwork";
+import { mapState } from "vuex";
+import timeMixins from "@/mixins/time";
+import DeleteAssignment from "@/components/AssignmentCRUD/DeleteAssignment";
+import UpdateAssignment from "@/components/AssignmentCRUD/UpdateAssignment";
+import CreateAssignment from "@/components/AssignmentCRUD/CreateAssignment";
+import PageSectionLoading from "@/components/PageBody/PageSectionLoading/index";
+import NoDataSvg from "@/components/NoDataSvg";
+
+export default {
+  components: {
+    PageBody,
+    PageHeader,
+    DeleteAssignment,
+    UpdateAssignment,
+    CreateAssignment,
+    PageSectionLoading,
+    NoDataSvg
+  },
+  mixins: [timeMixins],
+  mounted() {
+    this.loadingDlWorkList = true;
+    const { courseId } = this.$route.params;
+    getDLAssignmentListByTeacher(courseId).then(res => {
+      this.dlworkData = res.data;
+      this.loadingDlWorkList = false;
+    });
+  },
+  data() {
+    return {
+      dlworkData: [],
+      assignType: 0,
+      loadingDlWorkList: false
+    };
+  },
+  computed: {
+    ...mapState({
+      course: state => state.course.currentCourse
+    })
+  },
+  methods: {
+    pushNewAssignment(item) {
+      this.dlworkData.push(item);
+    },
+    updateData(modifiedItem) {
+      let length = this.dlworkData.length;
+      for (let i = 0; i < length; i++) {
+        if (modifiedItem.id === this.dlworkData[i].id) {
+          this.dlworkData.splice(i, 1, modifiedItem);
+          break;
+        }
+      }
+    },
+    deleteAssignment(delId) {
+      let length = this.dlworkData.length;
+      for (let i = 0; i < length; i++) {
+        if (this.dlworkData[i].id === delId) {
+          this.dlworkData.splice(i, 1);
+          break;
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.card {
+  padding: 30px;
+  .title {
+    font-size: 1.25rem;
+    small {
+      color: gray;
+      font-size: 1rem;
+    }
+  }
+  .content {
+    a {
+      margin-top: 30px;
+      width: 100%;
+    }
+  }
+}
+</style>

+ 0 - 19
tests/e2e/custom-assertions/elementCount.js

@@ -1,19 +0,0 @@
-// A custom Nightwatch assertion.
-// The assertion name is the filename.
-// Example usage:
-//
-//   browser.assert.elementCount(selector, count)
-//
-// For more information on custom assertions see:
-// http://nightwatchjs.org/guide#writing-custom-assertions
-
-exports.assertion = function elementCount(selector, count) {
-  this.message = `Testing if element <${selector}> has count: ${count}`;
-  this.expected = count;
-  this.pass = val => val === count;
-  this.value = res => res.value;
-  function evaluator(_selector) {
-    return document.querySelectorAll(_selector).length;
-  }
-  this.command = cb => this.api.execute(evaluator, [selector], cb);
-};

+ 0 - 14
tests/e2e/specs/test.js

@@ -1,14 +0,0 @@
-// For authoring Nightwatch tests, see
-// http://nightwatchjs.org/guide#usage
-
-module.exports = {
-  "default e2e tests": browser => {
-    browser
-      .url(process.env.VUE_DEV_SERVER_URL)
-      .waitForElementVisible("#app", 5000)
-      .assert.elementPresent(".hello")
-      .assert.containsText("h1", "Welcome to Your Vue.js App")
-      .assert.elementCount("img", 1)
-      .end();
-  }
-};

+ 0 - 5
tests/unit/.eslintrc.js

@@ -1,5 +0,0 @@
-module.exports = {
-  env: {
-    jest: true
-  }
-};

+ 0 - 15
tests/unit/api/polly.config.js

@@ -1,15 +0,0 @@
-import { Polly } from "@pollyjs/core";
-import FetchAdapter from "@pollyjs/adapter-fetch";
-import XHRAdapter from "@pollyjs/adapter-xhr";
-import LocalStoragePersister from "@pollyjs/persister-local-storage";
-
-Polly.register(FetchAdapter);
-Polly.register(XHRAdapter);
-Polly.register(LocalStoragePersister);
-
-export default Polly;
-
-export const pollyConfig = {
-  adapters: ["fetch", "xhr"],
-  persister: "local-storage"
-};

+ 0 - 22
tests/unit/api/user.spec.js

@@ -1,22 +0,0 @@
-import { setupPolly } from "setup-polly-jest";
-import "whatwg-fetch";
-const getPost = async id => {
-  const response = await fetch(`/posts/${id}`);
-
-  const json = await response.json();
-
-  return Object.assign(json, { ok: response.ok, status: response.status });
-};
-describe("user api test", () => {
-  let context = setupPolly({
-    /* default configuration options */
-  });
-
-  test("should have polly running with `test`", async () => {
-    const { server } = context.polly;
-    server.get("/posts/*path").intercept((req, res) => {
-      res.send(1);
-    });
-    expect(await getPost(1)).toHaveProperty("id", 1);
-  });
-});

+ 0 - 12
tests/unit/example.spec.js

@@ -1,12 +0,0 @@
-import { shallowMount } from "@vue/test-utils";
-import HelloWorld from "@/components/HelloWorld.vue";
-
-describe("HelloWorld.vue", () => {
-  it("renders props.msg when passed", () => {
-    const msg = "new message";
-    const wrapper = shallowMount(HelloWorld, {
-      propsData: { msg }
-    });
-    expect(wrapper.text()).toMatch(msg);
-  });
-});

Diferenças do arquivo suprimidas por serem muito extensas
+ 31 - 472
yarn.lock


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff