Explorar o código

需求树 & 做题记录

sky %!s(int64=4) %!d(string=hai) anos
pai
achega
1b1152d972

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 14885 - 1
package-lock.json


+ 1 - 1
package.json

@@ -33,7 +33,7 @@
     "express": "^4.17.1",
     "lint-staged": "^9.5.0",
     "mockjs": "^1.1.0",
-    "node-dev": "^4.0.0",
+    "node-dev": "^4.3.0",
     "prettier": "^1.19.1",
     "vue-template-compiler": "^2.6.11"
   },

+ 1 - 1
src/common/const.js

@@ -1,7 +1,7 @@
 // 部署url
 export const REQUEST_BASE_URL_PROD = "http://ismzl.com/";
 // 开发url (mock的地址
-export const REQUEST_BASE_URL_DEV = "http://127.0.0.1:3456/";
+export const REQUEST_BASE_URL_DEV = "http://127.0.0.1:12306/";
 // export const REQUEST_BASE_URL_DEV = "/api";
 export const ROLE = {
   STUDENT: "STUDENT", //学生身份

+ 53 - 0
src/components/content/Chart.vue

@@ -0,0 +1,53 @@
+<template>
+  <div :style="{ height: height, width: width }"></div>
+</template>
+
+<script>
+export default {
+  name: "Chart",
+  props: {
+    option: {
+      require: false,
+      default() {
+        return {};
+      }
+    },
+    width: {
+      require: false,
+      default() {
+        return "600px";
+      }
+    },
+    height: {
+      require: false,
+      default() {
+        return "300px";
+      }
+    }
+  },
+  data() {
+    return {
+      chart: null
+    };
+  },
+  watch: {
+    option(val) {
+      // console.log("哈哈哈哈");
+      this.init();
+    }
+  },
+  mounted() {
+    this.init();
+  },
+  methods: {
+    init() {
+      let chart = this.$echarts.init(this.$el);
+      chart.showLoading();
+      chart.setOption(this.option === undefined ? {} : this.option);
+      chart.hideLoading();
+    }
+  }
+};
+</script>
+
+<style scoped></style>

+ 5 - 1
src/components/content/Layout.vue

@@ -17,9 +17,13 @@
 				    <i class="el-icon-s-data"></i>
 				    <span slot="title">Competency-tree</span>
 				</el-menu-item>
+				<el-menu-item index="/questionList" v-if="permit([ROLE.STUDENT, ROLE.ADMIN])">
+				    <i class="el-icon-s-order"></i>
+				    <span slot="title">Question-list</span>
+				</el-menu-item>
                 <el-menu-item index="/teacherPage" v-if="permit([ROLE.TEACHER, ROLE.ADMIN])">
                     <i class="el-icon-receiving"></i>
-                    <span slot="title">TeacherPage</span>
+                    <span slot="title">Teacher-page</span>
                 </el-menu-item>
             </el-menu>
             <div class="logout-fix">

+ 1 - 1
src/mock/index.js

@@ -2,7 +2,7 @@ const mock = require("./utils");
 const express = require("express");
 const app = express();
 const bodyParser = require("body-parser");
-const port = 3456;
+const port = 12306;
 
 app.use(bodyParser.urlencoded({ extended: true }));
 app.use(bodyParser.json());

+ 12 - 2
src/router/index.js

@@ -5,6 +5,7 @@ import { auth } from "../network/auth";
 
 const Error = () => import("@/components/content/Error");
 const StudentPage = () => import("@/views/StudentPage");
+const QuestionList = () => import("@/views/QuestionList");
 const TeacherPage = () => import("@/views/TeacherPage");
 const Home = () => import("@/views/Home");
 
@@ -24,6 +25,11 @@ const routes = [
     component: StudentPage,
     meta: { requiresAuth: [ROLE.STUDENT,ROLE.ADMIN] }
   },
+  {
+    path: '/questionList',
+    component: QuestionList,
+    meta: { requiresAuth: [ROLE.STUDENT,ROLE.ADMIN] }
+  },
   {
     path: '/teacherPage',
     component: TeacherPage,
@@ -47,12 +53,16 @@ const router = new VueRouter({
 router.beforeEach(async (to,from,next) => {
   console.log(to.path, " ", from.path);
   let { id_token: token } = to.query;
-  // token = "123";
+  token = "123";
   if (token) {
     sessionStorage.setItem("token", token); // get token from the query param "id_token"
     // TODO : get user info from backend
     let res = null;
-    await auth().then(_res => res = _res);
+    await auth({
+      params: {
+        token: token
+      }
+    }).then(_res => res = _res);
     console.log(res);
     if(res?.data?.user_info) {
       sessionStorage.setItem("role", res.data.user_info.role);

+ 73 - 0
src/views/QuestionList.vue

@@ -0,0 +1,73 @@
+<template>
+  <Layout>
+    <Title title="做题记录"></Title>
+    <el-table :data="tableData" style="width: 100%">
+      <el-table-column prop="questionId" label="题目ID" sortable> </el-table-column>
+      <el-table-column prop="knowledgeType" label="知识点类型" sortable> </el-table-column>
+      <el-table-column prop="score" label="得分" sortable> </el-table-column>
+      <el-table-column prop="maxScore" label="总分" sortable> </el-table-column>
+      <el-table-column prop="proportion" label="得分占比" sortable> </el-table-column>
+      <el-table-column prop="time" label="做题日期" sortable> </el-table-column>
+    </el-table>
+  </Layout>
+</template>
+
+<script>
+  import Layout from "@/components/content/Layout";
+  import Title from "@/components/content/Title";
+  export default {
+    components: {
+      Layout,
+      Title,
+    },
+    data() {
+      return {
+        tableData: [
+          {
+            "questionId": 1,
+            "knowledgeType": "需求",
+            "score": 20,
+            "maxScore":30,
+            "proportion": 0.67,
+            "time": "2022-04-29 14:00:00"
+          },
+          {
+            "questionId": 2,
+            "knowledgeType": "设计",
+            "score": 20,
+            "maxScore":40,
+            "proportion": 0.5,
+            "time": "2022-04-29 14:00:00"
+          },
+          {
+            "questionId": 3,
+            "knowledgeType": "需求",
+            "score": 20,
+            "maxScore":50,
+            "proportion": 0.4,
+            "time": "2022-04-29 14:00:00"
+          },
+          {
+            "questionId": 4,
+            "knowledgeType": "需求",
+            "score": 20,
+            "maxScore":60,
+            "proportion": 0.33,
+            "time": "2022-04-27 14:00:00"
+          },
+          {
+            "questionId": 5,
+            "knowledgeType": "需求",
+            "score": 20,
+            "maxScore":30,
+            "proportion": 0.67,
+            "time": "2022-04-28 14:00:00"
+          },
+        ],
+      };
+    },
+  };
+</script>
+
+<style scoped>
+</style>

+ 371 - 3
src/views/StudentPage.vue

@@ -1,20 +1,388 @@
 <template>
   <Layout>
     <Title title="能力树模型"></Title>
-    TODO
+    <el-table
+      :data="tableData"
+      style="width: 100%; margin-bottom: 20px"
+      row-key="name"
+      border
+      height="780"
+      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+    >
+      <el-table-column prop="name" label="名称(Name)" width="180">
+        <template slot-scope="scope">
+          
+          <el-tooltip
+            class="item"
+            effect="dark"
+            content="点击进行相关题目推荐.."
+            placement="right"
+          >
+            <a href="#" @click="recommend(scope.row.name)" class="recommend"
+            >{{ scope.row.name }} 💁‍♂️</a
+          >
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column prop="score" label="得分(Score)" width="120">
+      </el-table-column>
+      <el-table-column label="分数组成(Score-Composition)">
+        <template slot-scope="scope">
+          <Chart
+            height="350px"
+            width="410px"
+            :option="getPieOption(scope.row.children)"
+          ></Chart>
+        </template>
+      </el-table-column>
+      <el-table-column prop="skills" label="技能(Skills)">
+        <template slot-scope="scope">
+          <Chart
+            height="350px"
+            :option="getRadarOption(scope.row.skills)"
+          ></Chart>
+        </template>
+      </el-table-column>
+      <el-table-column prop="disposition" label="态度(Disposition)">
+        <template slot-scope="scope">
+          <Chart
+            height="350px"
+            width="420px"
+            :option="getBarOption(scope.row.disposition, null)"
+          ></Chart>
+        </template>
+      </el-table-column>
+    </el-table>
   </Layout>
 </template>
 
 <script>
   import Layout from "@/components/content/Layout";
   import Title from "@/components/content/Title";
+  import Chart from "@/components/content/Chart";
   export default {
     components: {
-        Layout,
-        Title
+      Layout,
+      Title,
+      Chart,
+    },
+    data() {
+      return {
+        tableData: [
+          {
+            name: "软件工程",
+            score: 57,
+            skills: [1, 2, 3, 4, 5, 6],
+            disposition: [
+              { name: "细心", score: 45 },
+              { name: "责任心", score: 55 },
+              { name: "耐心", score: 25 },
+              { name: "合作能力", score: 75 },
+            ],
+            children: [
+              {
+                name: "需求",
+                score: 19,
+                skills: [1, 2, 3, 4, 5, 6],
+                disposition: [
+                  { name: "细心", score: 45 },
+                  { name: "责任心", score: 55 },
+                  { name: "耐心", score: 25 },
+                  { name: "合作能力", score: 75 },
+                ],
+                children: [
+                  {
+                    name: "需求基础",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                  {
+                    name: "需求XX",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                ],
+              },
+              {
+                name: "设计",
+                score: 19,
+                skills: [1, 2, 3, 4, 5, 6],
+                disposition: [
+                  { name: "细心", score: 45 },
+                  { name: "责任心", score: 55 },
+                  { name: "耐心", score: 25 },
+                ],
+                children: [
+                  {
+                    name: "设计1",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                  {
+                    name: "设计2",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                  {
+                    name: "设计3",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                ],
+              },
+              {
+                name: "测试",
+                score: 19,
+                skills: [1, 2, 3, 4, 5, 6],
+                disposition: [
+                  { name: "细心", score: 45 },
+                  { name: "责任心", score: 55 },
+                  { name: "耐心", score: 25 },
+                ],
+                children: [
+                  {
+                    name: "黑盒测试",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                  {
+                    name: "白盒测试",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                  {
+                    name: "验收测试",
+                    score: 19,
+                    skills: [1, 2, 3, 4, 5, 6],
+                    disposition: [
+                      { name: "细心", score: 45 },
+                      { name: "责任心", score: 55 },
+                      { name: "耐心", score: 25 },
+                    ],
+                  },
+                ],
+              },
+            ],
+          },
+        ],
+      };
+    },
+    methods: {
+      handleNodeClick(data) {
+        console.log(data);
+      },
+      recommend(knowledge) {
+        alert("推荐"+knowledge+"相关题目...")
+      },
+      getBarOption(disposition) {
+        // console.log("秒啊");
+        let tmp = {
+          name: [],
+          score: [],
+        };
+        for (let d of disposition) {
+          tmp.name.push(d.name);
+          tmp.score.push(d.score);
+        }
+        return {
+          tooltip: {
+            trigger: "item",
+            formatter: "{c} ({b})",
+          },
+          itemStyle: {
+            color: "#83a2ff",
+            shadowBlur: 200,
+            shadowColor: "rgba(23,48,103,0.5)",
+          },
+          xAxis: {
+            type: "category",
+            data: tmp.name,
+          },
+          yAxis: {
+            type: "value",
+            // show: false,
+            axisLine: {
+              lineStyle: {
+                color: "#555",
+              },
+            },
+            splitLine: {
+              show: false,
+            },
+          },
+          series: [
+            {
+              data: tmp.score,
+              type: "bar",
+              barMaxWidth: 40,
+              showBackground: true,
+              backgroundStyle: {
+                color: "rgba(220, 220, 220, 0.8)",
+              },
+              itemStyle: {
+                color: "#a17be3",
+              },
+            },
+          ],
+        };
+      },
+      getRadarOption(skills, max = [10, 10, 10, 10, 10, 10]) {
+        return {
+          tooltip: {
+            trigger: "item",
+          },
+          color: ["#67F9D8", "#FFE434", "#56A3F1", "#FF917C"],
+          radar: [
+            {
+              indicator: [
+                { text: "Remember", max: max[0] },
+                { text: "Understand", max: max[1] },
+                { text: "Apply", max: max[2] },
+                { text: "Analyze", max: max[3] },
+                { text: "Evaluation", max: max[4] },
+                { text: "Create", max: max[5] },
+              ],
+              center: ["35%", "50%"],
+              radius: 120,
+              startAngle: 90,
+              splitNumber: 4,
+              shape: "circle",
+              axisName: {
+                formatter: "【{value}】",
+                color: "#428BD4",
+              },
+              splitArea: {
+                areaStyle: {
+                  color: ["#77EADF", "#26C3BE", "#64AFE9", "#428BD4"],
+                  shadowBlur: 200,
+                  shadowColor: "rgba(23,48,103,0.5)",
+                },
+              },
+              axisLine: {
+                lineStyle: {
+                  color: () => "?",
+                },
+              },
+              splitLine: {
+                lineStyle: {
+                  color: "rgba(211, 253, 250, 0.8)",
+                },
+              },
+            },
+          ],
+          series: [
+            {
+              type: "radar",
+              emphasis: {
+                lineStyle: {
+                  width: 4,
+                },
+              },
+              data: [
+                {
+                  value: skills,
+                  name: "Skills",
+                  areaStyle: {
+                    color: "rgba(255, 228, 52, 0.6)",
+                  },
+                },
+              ],
+            },
+          ],
+        };
+      },
+      getPieOption(pieData) {
+        // console.log("piedata", pieData)
+        return {
+          tooltip: {
+            trigger: "item",
+            formatter: "{b} : {c} ({d}%)",
+          },
+          series: [
+            {
+              // name: '访问来源',
+              type: "pie",
+              radius: "55%",
+              center: ["50%", "50%"],
+              data: pieData
+                ? pieData.map((item) => {
+                    return {
+                      value: item.score,
+                      name: item.name,
+                    };
+                  })
+                : [],
+              roseType: "radius",
+              label: {
+                color: "#999999",
+              },
+              labelLine: {
+                lineStyle: {
+                  color: "#999999",
+                },
+                smooth: 0.2,
+                length: 10,
+                length2: 20,
+              },
+              itemStyle: {
+                color: "#83a2ff",
+                shadowBlur: 200,
+                shadowColor: "rgba(23,48,103,0.5)",
+              },
+
+              animationType: "scale",
+              animationEasing: "elasticOut",
+              animationDelay: function (idx) {
+                return Math.random() * 200;
+              },
+            },
+          ],
+        };
+      },
     },
   };
 </script>
 
 <style scoped>
+  ::v-deep .el-tree-node__content {
+    height: fit-content;
+  }
+  .recommend:hover {
+    color: red;
+  }
 </style>

+ 2 - 2
vue.config.js

@@ -3,10 +3,10 @@ module.exports = {
     devServer: {
       port: 8085,
       open: true,
-      host:"analysis.seecoder.cn",
+      host:"localhost",
       proxy: {
         '/api': {
-          target: 'http://localhost:8089',
+          target: 'http://localhost:12306',
           ws: true,
           changeOrigin: true,
           pathRewrite:{

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio