Browse Source

目标管理

zengyicheng 2 years ago
parent
commit
3d4c8b1121

File diff suppressed because it is too large
+ 1 - 15559
package-lock.json


+ 2 - 0
package.json

@@ -17,8 +17,10 @@
     "element-ui": "^2.15.6",
     "hevue-img-preview": "^5.0.3",
     "html2canvas": "^1.4.1",
+    "jsmind": "^0.4.8",
     "vue": "^2.5.2",
     "vue-cookies": "^1.7.4",
+    "vue-jsmind": "^1.5.0",
     "vue-pdf": "^4.3.0",
     "vue-router": "^3.0.1",
     "vue-video-player": "^5.0.2",

BIN
src/assets/nominddata.png


+ 1 - 13
src/components/index.vue

@@ -8,20 +8,8 @@
             <!-- <h3 class="small">{{ item }}</h3> -->
             <img
               class="imgS"
-              :src="item.poster"
+              src=""
               alt=""
-              @click.stop="
-                goTo(
-                  '/courseDetail?courseId=' +
-                    item.url +
-                    '&userid=' +
-                    userid +
-                    '&oid=' +
-                    oid +
-                    '&tType=' +
-                    tType
-                )
-              "
             />
           </el-carousel-item>
         </el-carousel>

+ 400 - 28
src/components/study.vue

@@ -251,7 +251,11 @@
                 </div>
                 <div
                   class="vedioList"
-                  :class="vedio[taskCount].length == 0 && file[taskCount].length == 0 ? 'listNoVedio' : ''"
+                  :class="
+                    vedio[taskCount].length == 0 && file[taskCount].length == 0
+                      ? 'listNoVedio'
+                      : ''
+                  "
                   v-if="
                     (vedio.length &&
                       vedio[taskCount] &&
@@ -1335,38 +1339,113 @@
                 </div>-->
                 评一评
               </div>
-              <div class="elist_input">
-                <div
-                  v-for="(eItem, eIndex) in chapInfoList[courseType]
-                    .chapterInfo[0].taskJson[taskCount].eList"
-                  :key="eIndex"
-                  class="elist_input_box"
-                >
-                  <div>
-                    <div
-                      style="
-                        display: flex;
-                        flex-direction: row;
-                        flex-wrap: nowrap;
-                        align-items: center;
-                      "
-                    >
-                      <div>
-                        <span>{{ eItem.value }} </span>
-                      </div>
+              <div class="evaCss">
+                <div class="elist_input">
+                  <div
+                    v-for="(eItem, eIndex) in chapInfoList[courseType]
+                      .chapterInfo[0].taskJson[taskCount].eList"
+                    :key="eIndex"
+                    class="elist_input_box"
+                  >
+                    <div>
                       <div
                         style="
-                          padding-left: 25px;
                           display: flex;
                           flex-direction: row;
+                          flex-wrap: nowrap;
                           align-items: center;
                         "
                       >
-                        <el-rate v-model="eItem.score" disabled></el-rate>
+                        <div>
+                          <span>{{ eItem.value }} </span>
+                        </div>
+                        <div
+                          style="
+                            padding-left: 25px;
+                            display: flex;
+                            flex-direction: row;
+                            align-items: center;
+                          "
+                        >
+                          <el-rate v-model="eItem.score" disabled></el-rate>
+                        </div>
+                      </div>
+                      <div class="elist_inptu_text" style="padding-left: 10px">
+                        <span>{{ eItem.detail }} </span>
                       </div>
                     </div>
-                    <div class="elist_inptu_text" style="padding-left: 10px">
-                      <span>{{ eItem.detail }} </span>
+                  </div>
+                </div>
+                <div
+                  v-if="evalua != ''"
+                  style="
+                    border: 1px solid #e5e5e5;
+                    width: 55%;
+                    margin-top: 20px;
+                    box-shadow: 3px 1px 15px 3px #e0e0e0;
+                  "
+                >
+                  <div class="e_add_top">
+                    <div class="e_add_title">
+                      <span>目标管理名称</span>
+                      <span>{{ eTitle }} </span>
+                      <img
+                        src="../assets/line.png"
+                        class="cru_line"
+                        style="
+                          width: 125px;
+                          height: 20px;
+                          bottom: -10px;
+                          left: 120px;
+                        "
+                      />
+                      <!-- <el-input
+                        v-model="eTitle"
+                        placeholder="请输入名称"
+                        @change="setMindData"
+                      ></el-input> -->
+                    </div>
+                  </div>
+                  <div class="e_add_content">
+                    <div class="e_add_list_pbox">
+                      <div class="e_add_list_pbox_title">
+                        <span class="type_title">切换模式</span>
+                        <div class="type_content">
+                          <span
+                            :class="{ active: typeMode == 1 }"
+                            @click="typeMode = 1"
+                            >目标树</span
+                          >
+                          <span
+                            :class="{ active: typeMode == 2 }"
+                            @click="typeMode = 2"
+                            >目标罗盘</span
+                          >
+                          <span
+                            :class="{ active: typeMode == 3 }"
+                            @click="typeMode = 3"
+                            >目标看板</span
+                          >
+                        </div>
+                      </div>
+                      <div class="e_add_list_pbox_content">
+                        <Mind
+                          :showBar="false"
+                          :mindData="data"
+                          v-show="typeMode == 1"
+                        ></Mind>
+                        <Sunburst
+                          :Josn="eJson"
+                          :num="eJSONNum"
+                          v-if="typeMode == 2"
+                        ></Sunburst>
+                        <SeeBoard
+                          :Josn="eJson"
+                          :num="eJSONNum"
+                          :ename="eTitle"
+                          v-if="typeMode == 3"
+                        ></SeeBoard>
+                      </div>
                     </div>
                   </div>
                 </div>
@@ -1752,7 +1831,7 @@
               <img src="../assets/icon/question.png" alt />
             </div>
             <div class="queTitle">
-              <div>提问:</div>
+              <div style="width:90px;min-width:90px;">提问:</div>
               <div>{{ answerQ }}</div>
             </div>
           </div>
@@ -1796,8 +1875,11 @@ import pdf from "./components/pdf2";
 import AskStatic from "./components/askStatic";
 import EditorBar from "../components/tools/wangEnduit.vue";
 import Time from "../components/tools/time.vue";
+import Mind from "./tools/jsmind.vue";
+import Sunburst from "./tools/sunburst";
+import SeeBoard from "./tools/seeBoard";
 export default {
-  components: { EditorBar, Time, pdf, AskStatic },
+  components: { EditorBar, Time, pdf, AskStatic, Mind, Sunburst, SeeBoard },
   data() {
     return {
       dialogVisible: false,
@@ -1923,6 +2005,26 @@ export default {
       fileType: 0,
       showPDF: false,
       noteName: "",
+      evaJuri: [],
+      evalua: "",
+      eTitle: "",
+      eName: "",
+      eJson: {},
+      fid: "", //一级
+      sid: "", //二级
+      tid: "", //二级
+      typeMode: 1,
+      eJSONNum: 0,
+      Etype: 1,
+      data: {
+        meta: {
+          name: "example",
+          author: "dd@163.com",
+          version: "0.2",
+        },
+        format: "node_array",
+        data: [{ id: "root", isroot: true, topic: "" }],
+      },
     };
   },
   methods: {
@@ -2631,6 +2733,7 @@ export default {
             this.playerO[i] = d;
           }
           this.courseDetail = res.data[0][0];
+          this.evalua = res.data[0][0].evaId;
           this.chapInfo = JSON.parse(this.courseDetail.chapters)[
             this.courseType
           ];
@@ -2702,7 +2805,7 @@ export default {
               this.text = this.textList[this.taskCount][0];
             }
           }
-
+          this.checkEva();
           this.selectStudent();
           this.selectSWorks();
           let _this = this;
@@ -3242,6 +3345,68 @@ export default {
           console.error(err);
         });
     },
+    checkEva() {
+      if (this.evalua != "") {
+        for (var i = 0; i < this.evaJuri.length; i++) {
+          if (this.evalua == this.evaJuri[i].id) {
+            this.eTitle = this.evaJuri[i].title;
+            this.eJson = JSON.parse(this.evaJuri[i].content);
+          }
+        }
+        this.$forceUpdate();
+        setTimeout(() => {
+          this.setMindData();
+        }, 0);
+      }
+    },
+    selectEva() {
+      let params = {
+        oid: this.oid,
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectAllEvaluation", params)
+        .then((res) => {
+          this.evaJuri = res.data[0];
+        })
+        .catch((err) => {
+          console.error(err);
+        });
+    },
+    setMindData() {
+      this.data.data = [];
+      this.data.data.push({ id: "root", isroot: true, topic: this.eTitle });
+      let _eJson = Object.keys(this.eJson);
+      let _e = this.eJson;
+      for (let i = 0; i < _eJson.length; i++) {
+        let element = _e[_eJson[i]];
+        this.data.data.push({
+          id: element.id,
+          parentid: "root",
+          topic: element.name,
+        });
+        let _eJsonc = Object.keys(element.child);
+        let _e2 = element.child;
+        for (let j = 0; j < _eJsonc.length; j++) {
+          let _ec = _e2[_eJsonc[j]];
+          this.data.data.push({
+            id: _ec.id,
+            parentid: element.id,
+            topic: _ec.name,
+          });
+          let _eJsonz = Object.keys(_ec.child);
+          let _e3 = _ec.child;
+          for (let z = 0; z < _eJsonz.length; z++) {
+            let _ez = _e3[_eJsonz[z]];
+            this.data.data.push({
+              id: _ez.id,
+              parentid: _ec.id,
+              topic: _ez.name,
+            });
+          }
+        }
+      }
+      this.$forceUpdate();
+    },
   },
   destroyed() {
     window.onresize = null;
@@ -3259,6 +3424,7 @@ export default {
     },
   },
   created() {
+    this.selectEva();
     this.getCourseDetail();
     this.selectCount();
     this.getHomeWork();
@@ -4432,7 +4598,9 @@ export default {
   padding: 10px 0 15px 30px;
   flex-direction: column;
 }
-
+.elist_input {
+  width: 40%;
+}
 .elist_input .elist_input_box input {
   font: inherit;
   color: currentColor;
@@ -4520,4 +4688,208 @@ export default {
   border-radius: 10px;
   box-shadow: 0 0 6px 1px #dfdada;
 }
+.e_add_top {
+  display: flex;
+  justify-content: space-between;
+  padding: 20px 20px 0 20px;
+  border-radius: 3px;
+  background: #fff;
+}
+.e_add_title2 {
+  display: flex;
+  align-items: center;
+}
+
+.e_add_title2 span {
+  width: 40px;
+}
+
+.e_add_title {
+  display: flex;
+  align-items: center;
+  color: #b8b8b8;
+  font-size: 18px;
+  position: relative;
+  height: 40px;
+}
+.e_add_title span {
+  margin-right: 10px;
+}
+.e_add_title .el_input {
+  width: 300px;
+}
+.e_add_title >>> .el-input__inner {
+  width: 400px;
+}
+
+.e_add_btn {
+}
+.e_add_content {
+  display: flex;
+  width: 750px;
+  height: 550px;
+}
+.e_add_list {
+  background: #fff;
+  height: 500px;
+  width: 210px;
+  position: relative;
+  margin: 15px 5px 0 0;
+  flex-shrink: 0;
+  display: flex;
+  flex-direction: column;
+}
+.e_add_list_title {
+  font-size: 20px;
+  width: 100%;
+  box-sizing: border-box;
+  padding: 15px 40px;
+  text-align: center;
+  border-bottom: 1px solid #eaeaea;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 57px;
+  background: #f6f6f6;
+}
+.e_add_list_title span {
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.e_add_list_title img {
+  position: absolute;
+  right: 15px;
+  width: 25px;
+  cursor: pointer;
+  top: 50%;
+  transform: translateY(-50%);
+}
+.e_add_list_body {
+  height: calc(100% - 187px);
+  overflow: auto;
+}
+.e_add_list_child {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+  box-sizing: border-box;
+  padding: 15px 40px;
+  text-align: center;
+}
+.e_add_list_child span {
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  cursor: pointer;
+}
+.e_add_list_child img {
+  position: absolute;
+  right: 10px;
+  width: 21px;
+  cursor: pointer;
+  top: 50%;
+  transform: translateY(-50%);
+}
+.e_add_list_child + .e_add_list_child {
+  border-top: 1px solid #eaeaea;
+}
+.e_add_list_child .active {
+  color: #409eff;
+}
+.e_add_list_btn {
+  position: absolute;
+  bottom: 0;
+  height: 50px;
+  background: rgb(120, 120, 254);
+  width: 100%;
+  color: #fff;
+  font-size: 16px;
+  text-align: center;
+  line-height: 50px;
+  cursor: pointer;
+}
+.e_add_list_detail {
+  position: absolute;
+  bottom: 0;
+  height: 130px;
+  background: rgb(120, 120, 254);
+  width: 100%;
+  color: #fff;
+  font-size: 16px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.e_add_list_detail textarea {
+  height: 90%;
+  width: 95%;
+  border: none;
+  resize: none;
+  outline: none;
+  padding: 5px;
+  box-sizing: border-box;
+}
+
+.e_add_list_pbox {
+  width: 750px;
+  /* height: 600px; */
+}
+.e_add_list_pbox_title {
+  height: 50px;
+  background: #fff;
+  display: flex;
+  align-items: center;
+  width: 100%;
+  box-sizing: border-box;
+  padding: 0 20px;
+}
+
+.type_title {
+  font-size: 18px;
+  font-weight: 700;
+}
+.type_content {
+  font-size: 16px;
+  margin-left: 30px;
+}
+.type_content span + span {
+  margin-left: 20px;
+}
+.type_content span {
+  cursor: pointer;
+  padding-bottom: 5px;
+  box-sizing: border-box;
+}
+
+.type_content .active {
+  color: #409eff;
+  border-bottom: 2px solid #409eff;
+}
+
+.e_add_list_pbox_content {
+  height: calc(100% - 50px);
+  display: flex;
+  align-items: center;
+  width: 100%;
+  background: #fff;
+}
+.evaCss {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+}
+.cru_line {
+  position: absolute;
+  bottom: 0px;
+  transition: all 0.5s;
+  left: 0px;
+  width: 125px;
+  margin-left: -25px;
+}
+
 </style>

+ 550 - 0
src/components/tools/jsmind.vue

@@ -0,0 +1,550 @@
+<template>
+  <!-- 普通菜单 -->
+  <div class="jsmind_layout">
+    <div class="noMind" v-if="mindV">
+      <img src="../../assets/nominddata.png" alt />
+    </div>
+    <!-- <div class="jsmind_toolbar" v-if="showBar">
+      <el-upload
+        class="pad"
+        :multiple="false"
+        ref="upload"
+        action="action"
+        :before-upload="beforeUpload"
+        :http-request="upload"
+      >
+        <el-button type="primary" size="medium">导入</el-button>
+      </el-upload>
+      <el-button @click="save_nodearray_file" size="medium">保存</el-button>
+      <el-button @click="screen_shot" size="medium">下载导图</el-button>
+      <el-button @click="get_nodearray_data" size="medium">获取数据</el-button>
+      <el-button @click="addNode" size="medium">新增节点</el-button>
+      <el-button @click="addBrotherNode" size="medium">新增兄弟节点</el-button>
+      <el-button @click="editNode" size="medium">编辑节点</el-button>
+      <el-button @click="removeNode" size="medium">删除节点</el-button>
+      <el-button @click="zoomIn" size="medium" :disabled="isZoomIn">放大</el-button>
+      <el-button @click="zoomOut" size="medium" :disabled="isZoomOut" class="pad">缩小</el-button>
+      <span>展开:</span>
+      <el-select
+        v-model="level"
+        placeholder="展开节点"
+        @change="expand_to_level"
+        class="pad pad-left"
+        size="medium"
+      >
+        <el-option
+          v-for="item in nodeOptions"
+          :key="item.value"
+          :label="item.label"
+          :value="item.value"
+        ></el-option>
+      </el-select>
+      <span>主题:</span>
+      <el-select v-model="localTheme" placeholder="选择主题" @change="set_theme" size="medium">
+        <el-option
+          v-for="item in themeOptions"
+          :key="item.value"
+          :label="item.label"
+          :value="item.value"
+        ></el-option>
+      </el-select>
+    </div>-->
+    <div id="jsmind_container" ref="container"></div>
+    <!-- <el-drawer title="编辑节点" :visible.sync="dialogVisible" size="500px">
+      <el-form label-width="80px" class="form-con">
+        <el-form-item label="字体大小">
+          <el-input-number
+            controls-position="right"
+            v-model.number="nodeOption.fontSize"
+            class="ele-width"
+            :min="1"
+            :max="30"
+            maxlength="2"
+          ></el-input-number>
+        </el-form-item>
+        <el-form-item label="字体粗细">
+          <el-select v-model="nodeOption.fontWeight" class="ele-width">
+            <el-option value="normal" label="常规"></el-option>
+            <el-option value="bold" label="粗体"></el-option>
+            <el-option value="bolder" label="更粗"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="字体样式">
+          <el-select v-model="nodeOption.fontStyle" class="ele-width">
+            <el-option value="normal" label="标准"></el-option>
+            <el-option value="italic" label="斜体"></el-option>
+            <el-option value="oblique" label="倾斜"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="背景颜色">
+              <el-color-picker v-model="nodeOption.bgColor" show-alpha size="mini"></el-color-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="字体颜色">
+              <el-color-picker v-model="nodeOption.fontColor" show-alpha size="mini"></el-color-picker>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="节点内容">
+          <el-input
+            type="textarea"
+            :rows="2"
+            v-model="nodeOption.content"
+            class="ele-width"
+            maxlength="64"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <template v-slot:footer>
+        <div class="right mr-10">
+          <el-button type="primary" class="common-btn" @click="sureEditNode" size="medium">确 定</el-button>
+        </div>
+      </template>
+    </el-drawer>-->
+  </div>
+</template>
+
+<script>
+import "jsmind/style/jsmind.css";
+import jsMind from "jsmind/js/jsmind.js";
+window.jsMind = jsMind;
+
+require("jsmind/js/jsmind.draggable.js");
+require("jsmind/js/jsmind.screenshot.js");
+export default {
+  props: {
+    showBar: {
+      // 是否显示工具栏,显示启用编辑
+      type: Boolean,
+      default: true,
+    },
+    theme: {
+      // 主题
+      type: String,
+      default: "primary",
+    },
+    lineColor: {
+      // 线条颜色
+      type: String,
+      default: "skyblue",
+    },
+    mindData: {
+      type: Object,
+      default: {},
+    },
+  },
+  data() {
+    return {
+      mindV: false,
+      i: 0,
+      mind: {},
+      jm: null,
+      isZoomIn: false,
+      isZoomOut: false,
+      level: 0,
+      nodeOptions: [
+        { value: 1, label: "展开到一级节点" },
+        { value: 2, label: "展开到二级节点" },
+        { value: 3, label: "展开到三级节点" },
+        { value: 0, label: "展开全部节点" },
+        { value: -1, label: "隐藏全部节点" },
+      ],
+      themeOptions: [
+        { value: "default", label: "default" },
+        { value: "primary", label: "primary" },
+        { value: "warning", label: "warning" },
+        { value: "danger", label: "danger" },
+        { value: "success", label: "success" },
+        { value: "info", label: "info" },
+        { value: "greensea", label: "greensea" },
+        { value: "nephrite", label: "nephrite" },
+        { value: "belizehole", label: "belizehole" },
+        { value: "wisteria", label: "wisteria" },
+        { value: "asphalt", label: "asphalt" },
+        { value: "orange", label: "orange" },
+        { value: "pumpkin", label: "pumpkin" },
+        { value: "pomegranate", label: "pomegranate" },
+        { value: "clouds", label: "clouds" },
+        { value: "asbestos", label: "asbestos" },
+      ],
+      localTheme: this.theme,
+      dialogVisible: false,
+      nodeOption: {
+        content: "",
+        bgColor: "",
+        fontColor: "",
+        fontSize: "",
+        fontWeight: "",
+        fontStyle: "",
+      },
+    };
+  },
+  watch: {
+    mindData: {
+      handler: function (cur, old) {
+        this.mind = cur;
+        if (cur.data[0].topic === "" && cur.data.length === 1) {
+          this.mindV = true;
+        } else {
+          this.mindV = false;
+        }
+        if (this.jm) {
+          this.jm.show(this.mind);
+        } else {
+          this.open_empty();
+        }
+      },
+      deep: true, //对象内部的属性监听,也叫深度监听
+    },
+  },
+  created() {},
+  mounted() {
+    this.getData();
+    // this.mouseWheel();
+  },
+  methods: {
+    beforeUpload(file) {
+      // 上传文件之前钩子
+      if (file) {
+        jsMind.util.file.read(file, (jsmindData) => {
+          const mind = jsMind.util.json.string2json(jsmindData);
+          if (mind) {
+            this.jm.show(mind);
+            this.$message({ type: "success", message: "打开成功" });
+          } else {
+            this.prompt_info("不能打开mindmap文件");
+          }
+        });
+      } else {
+        this.prompt_info("请先选择文件");
+        return false;
+      }
+    },
+    upload() {},
+    getData() {
+      //   this.$API({
+      //     name: "getMind",
+      //   })
+      //     .then((res) => {
+      //       this.mind = res.data;
+      //       this.open_empty();
+      //     })
+      //     .catch((error) => {
+      //       this.$message.error(error);
+      //     });
+      if (
+        !this.mind.data ||
+        (this.mind.data[0].topic === "" && this.mind.data.length === 1)
+      ) {
+        this.mindV = true;
+      } else {
+        this.mindV = false;
+      }
+      this.mind = this.mindData;
+      this.open_empty();
+    },
+    open_empty() {
+      const options = {
+        container: "jsmind_container", // 必选,容器ID
+        editable: this.showBar, // 可选,是否启用编辑
+        theme: this.localTheme, // 可选,主题
+        view: {
+          line_width: 2, // 思维导图线条的粗细
+          // line_color: this.lineColor, // 思维导图线条的颜色
+        },
+        shortcut: {
+          enable: true, // 禁用快捷键
+        },
+        layout: {
+          hspace: 20, // 节点之间的水平间距
+          vspace: 10, // 节点之间的垂直间距
+          pspace: 13, // 节点与连接线之间的水平间距(用于容纳节点收缩/展开控制器)
+        },
+        mode: "side", // 显示模式,子节点只分布在根节点右侧
+      };
+      this.jm = jsMind.show(options, this.mind);
+      // 改变窗口大小重置画布
+      window.onresize = () => {
+        this.jm.resize();
+      };
+      this.getDepth(this.jm.mind.root, 1);
+      this.$forceUpdate();
+    },
+    // 获取层级数 i
+    getDepth(obj, k) {
+      this.i = Math.max(this.i, k);
+      if (obj.children) {
+        obj.children.forEach((v) => {
+          this.getDepth(v, k + 1);
+        });
+      }
+    },
+    save_nodearray_file() {
+      const mindData = this.jm.get_data("node_array");
+      const mindName = mindData.meta.name;
+      const mindStr = jsMind.util.json.json2string(mindData);
+      jsMind.util.file.save(mindStr, "text/jsmind", mindName + ".jm");
+    },
+    screen_shot() {
+      this.jm.screenshot.shootDownload();
+    },
+    expand_all() {
+      this.jm.expand_all();
+    },
+    collapse_all() {
+      this.jm.collapse_all();
+    },
+    expand_to_level(num) {
+      switch (num) {
+        case -1:
+          this.collapse_all();
+          break;
+        case 0:
+          this.expand_all();
+          break;
+        default:
+          this.jm.expand_to_depth(num);
+          break;
+      }
+    },
+    zoomIn() {
+      if (this.jm.view.zoomIn()) {
+        this.isZoomOut = false;
+      } else {
+        this.isZoomIn = true;
+      }
+    },
+    zoomOut() {
+      debugger;
+      if (this.jm.view.zoomOut()) {
+        this.isZoomIn = false;
+      } else {
+        this.isZoomOut = true;
+      }
+    },
+    prompt_info(msg) {
+      this.$message({ type: "warning", message: msg });
+    },
+    get_nodearray_data() {
+      const mindData = this.jm.get_data("node_array");
+      const mindString = jsMind.util.json.json2string(mindData);
+      this.$message({ type: "info", message: mindString });
+    },
+    set_theme(themeName) {
+      this.jm.set_theme(themeName);
+    },
+    scrollFunc(e) {
+      e = e || window.event;
+      if (e.wheelDelta) {
+        if (e.wheelDelta > 0) {
+          this.zoomIn();
+        } else {
+          this.zoomOut();
+        }
+      } else if (e.detail) {
+        if (e.detail > 0) {
+          this.zoomIn();
+        } else {
+          this.zoomOut();
+        }
+      }
+      this.jm.resize();
+    },
+    // 鼠标滚轮放大缩小
+    mouseWheel() {
+      if (document.addEventListener) {
+        document.addEventListener("domMouseScroll", this.scrollFunc, false);
+      }
+      this.$refs.container.onmousewheel = this.scrollFunc;
+    },
+    // 新增节点
+    addNode() {
+      let selectedNode = this.jm.get_selected_node();
+      if (!selectedNode) {
+        this.$message({ type: "warning", message: "请先选择一个节点!" });
+        return;
+      }
+      let nodeid = jsMind.util.uuid.newid();
+      let topic = "new Node";
+      let newNode = this.jm.add_node(selectedNode, nodeid, topic);
+      if (newNode) {
+        this.jm.select_node(nodeid);
+        this.jm.begin_edit(nodeid);
+        this.getDepth(this.jm.mind.root, 1);
+      }
+    },
+    // 新增兄弟节点
+    addBrotherNode() {
+      let selectedNode = this.jm.get_selected_node();
+      if (!selectedNode) {
+        this.$message({ type: "warning", message: "请先选择一个节点!" });
+        return;
+      } else if (selectedNode.isroot) {
+        this.$message({
+          type: "warning",
+          message: "不能在根节点添加,请重新选择节点!",
+        });
+        return;
+      }
+      let nodeid = jsMind.util.uuid.newid();
+      let topic = "new Node";
+      let newNode = this.jm.insert_node_after(selectedNode, nodeid, topic);
+      if (newNode) {
+        this.jm.select_node(nodeid);
+        this.jm.begin_edit(nodeid);
+      }
+    },
+    // 获取选中标签的 ID
+    get_selected_nodeid() {
+      let selectedNode = this.jm.get_selected_node();
+      if (selectedNode) {
+        return selectedNode.id;
+      } else {
+        return null;
+      }
+    },
+    // 删除节点
+    removeNode() {
+      let selectedId = this.get_selected_nodeid();
+      if (!selectedId) {
+        this.$message({
+          type: "warning",
+          message: "请先选择一个节点!",
+        });
+        return;
+      }
+      this.jm.remove_node(selectedId);
+      this.i = 0;
+      this.getDepth(this.jm.mind.root, 1);
+    },
+    // 编辑节点
+    editNode() {
+      let selectedId = this.get_selected_nodeid();
+      if (!selectedId) {
+        this.$message({ type: "warning", message: "请先选择一个节点!" });
+        return;
+      }
+      let nodeObj = this.jm.get_node(selectedId);
+      this.nodeOption.content = nodeObj.topic;
+      this.nodeOption.bgColor = nodeObj.data["background-color"];
+      this.nodeOption.fontColor = nodeObj.data["foreground-color"];
+      this.nodeOption.fontSize = nodeObj.data["font-size"];
+      this.nodeOption.fontWeight = nodeObj.data["font-weight"];
+      this.nodeOption.fontStyle = nodeObj.data["font-style"];
+      this.dialogVisible = true;
+    },
+    sureEditNode() {
+      let selectedId = this.get_selected_nodeid();
+      this.jm.update_node(selectedId, this.nodeOption.content);
+      this.jm.set_node_font_style(
+        selectedId,
+        this.nodeOption.fontSize,
+        this.nodeOption.fontWeight,
+        this.nodeOption.fontStyle
+      );
+      this.jm.set_node_color(
+        selectedId,
+        this.nodeOption.bgColor,
+        this.nodeOption.fontColor
+      );
+      this.nodeOption = {
+        content: "",
+        bgColor: "",
+        fontColor: "",
+        fontSize: "",
+        fontWeight: "",
+        fontStyle: "",
+      };
+      this.dialogVisible = false;
+    },
+  },
+  beforeDestroy() {
+    // document.removeEventListener("domMouseScroll", this.scrollFunc, false);
+  },
+};
+</script>
+
+<style scoped>
+.jsmind_layout {
+  display: flex;
+  flex-direction: column;
+  width: 700px;
+  height: calc(100%);
+  /* height: 500px; */
+  /* margin: 15px 5px 0 0; */
+  background: #fff;
+  overflow: hidden;
+  flex-shrink: 0;
+  position: relative;
+}
+.jsmind_title {
+  position: absolute;
+  top: 20px;
+  left: 20px;
+  font-size: 20px;
+  color: #8d8d8d;
+}
+.noMind {
+  position: absolute;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+  z-index: 999;
+  background: #fff;
+}
+.jsmind_layout .jsmind_toolbar {
+  width: 100%;
+  padding: 0 10px 10px 10px;
+  height: auto;
+  flex-shrink: 0;
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  background-color: #f8f9fa;
+  box-shadow: 0 0 4px #b8b8b8;
+}
+.jsmind_layout >>> .el-button--medium,
+.jsmind_layout >>> .el-input--medium {
+  margin-top: 10px;
+}
+.jsmind_layout #jsmind_container {
+  /* flex: 1 1 auto; */
+  height: 100%;
+}
+.jsmind_layout >>> .jsmind-inner {
+  /* overflow: hidden auto !important; */
+  /* height: auto; */
+}
+.jsmind_layout >>> .el-upload-list {
+  display: none !important;
+}
+/* 隐藏滚动条 */
+.jsmind_layout .jsmind-inner::-webkit-scrollbar {
+  display: none;
+}
+.jsmind_layout .pad {
+  margin-right: 10px;
+}
+.jsmind_layout .pad-left {
+  margin-left: 10px;
+}
+.jsmind_layout >>> jmnode.selected {
+  background-color: #b9b9b9;
+  color: #fff;
+  box-shadow: 2px 2px 8px #777;
+}
+.jsmind_layout >>> jmnode:hover {
+  box-shadow: 2px 2px 8px #777;
+}
+.jsmind_layout .form-con {
+  padding-top: 20px;
+}
+.jsmind_layout .ele-width {
+  width: 96%;
+}
+</style>

+ 244 - 0
src/components/tools/seeBoard.vue

@@ -0,0 +1,244 @@
+<template>
+  <div class="data_body">
+    <div class="noMind" v-if="mindV">
+      <img src="../../assets/nominddata.png" alt />
+    </div>
+    <!-- <img src="../../assets/dataimage/1.png" style="width:90%" /> -->
+    <div class="b_box">
+      <div class="b_box_table">
+        <div class="bbt_title">{{ ename }}</div>
+        <div class="bbt_content">
+          <div v-for="(item, index) in ooption" :key="index" class="bbt_c1">
+            <div
+              class="bbt_c1_div"
+              :class="{ bbn: index == ooption.length - 1 }"
+            >
+              {{ item.name }}
+            </div>
+            <div class="bbt_c2">
+              <div
+                v-for="(item2, index2) in item.children"
+                :key="index + '-' + index2"
+                class="bbt_c1"
+              >
+                <div
+                  class="bbt_c2_div"
+                  :class="{
+                    bbn:
+                      index2 == item.children.length - 1 &&
+                      index == ooption.length - 1,
+                  }"
+                >
+                  {{ item2.name }}
+                </div>
+                <div class="bbt_c3">
+                  <div
+                    v-for="(item3, index3) in item2.children"
+                    :key="index + '-' + index2 + '-' + index3"
+                    :class="{
+                      bbn:
+                        index2 == item.children.length - 1 &&
+                        index == ooption.length - 1 &&
+                        index3 == item2.children.length - 1,
+                    }"
+                  >
+                    {{ item3.name }}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: ["Josn", "num", "ename"],
+  data() {
+    return {
+      mindV: true,
+      ooption: [],
+    };
+  },
+  methods: {
+    setData() {
+      if (!Object.keys(this.Josn).length) {
+        this.mindV = true;
+      } else {
+        this.mindV = false;
+      }
+      var res = this.Josn;
+      var _array = [];
+      let i = 0;
+      for (var item in res) {
+        let num = Object.keys(res);
+        let count = 10 / num.length;
+        let _item = res[item];
+        _array.push({ name: _item.name, value: count, children: [] });
+        let j = 0;
+        for (var item2 in _item.child) {
+          let num2 = Object.keys(res);
+          let count2 = count / num2.length;
+          let _item2 = _item.child[item2];
+          _array[i].children.push({
+            name: _item2.name,
+            value: count2,
+            children: [],
+          });
+          for (var item3 in _item2.child) {
+            let num3 = Object.keys(res);
+            let count3 = count2 / num3.length;
+            let _item3 = _item2.child[item3];
+            _array[i].children[j].children.push({
+              name: _item3.name,
+              value: count3,
+            });
+          }
+          j++;
+        }
+        i++;
+        console.log(item);
+      }
+      this.ooption = _array;
+    },
+  },
+  watch: {
+    num: {
+      handler: function (newVal, oldVal) {
+        this.setData();
+      },
+      deep: true,
+    },
+    Josn: {
+      handler: function (newVal, oldVal) {},
+      deep: true,
+    },
+  },
+  mounted() {
+    this.setData();
+  },
+};
+</script>
+
+<style scoped>
+.data_body {
+  /* display: flex; */
+  /* flex-direction: column; */
+  width: 500px;
+  height: 450px;
+  /* height: 500px; */
+  /* margin: 15px 5px 0 0; */
+  background: #fff;
+  overflow: hidden;
+  flex-shrink: 0;
+  position: relative;
+}
+.noMind {
+  position: absolute;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+  z-index: 999;
+  background: #fff;
+}
+
+.b_box {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  overflow: auto;
+}
+
+.b_box_table {
+  border: 2px solid #000;
+  height: fit-content;
+  width: auto;
+  margin: 20px 0;
+}
+
+.bbt_content {
+}
+
+.bbt_title {
+  height: 50px;
+  width: 330px;
+  border-bottom: 2px solid #000;
+  text-align: center;
+  line-height: 50px;
+  font-size: 18px;
+  background: rgb(57, 76, 165);
+  color: #fff;
+}
+.bbt_c1 {
+  display: flex;
+  width: 100%;
+}
+.bbt_c1_div {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-bottom: 2px solid #000;
+  max-width: 110px;
+  width: 110px;
+  min-height: 50px;
+  font-size: 16px;
+  background: rgb(171, 179, 214);
+  color: #000;
+  box-sizing: border-box;
+  padding: 5px 10px;
+}
+.bbt_c2 {
+  display: flex;
+  flex-direction: column;
+  max-width: 220px;
+  width: 220px;
+  border-left: 2px solid #000;
+  box-sizing: border-box;
+}
+.bbt_c2_div {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  max-width: 110px;
+  width: 110px;
+  border-bottom: 2px solid #000;
+  min-height: 50px;
+  background: rgb(189, 194, 226);
+  color: #000;
+  box-sizing: border-box;
+  padding: 5px 10px;
+}
+.bbt_c3 {
+  display: flex;
+  flex-direction: column;
+  max-width: 110px;
+  width: 110px;
+  border-left: 2px solid #000;
+}
+.bbt_c3 > div {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 50px;
+  width: 100%;
+  height: 100%;
+  background: rgb(214, 216, 234);
+  color: #000;
+  border-bottom: 2px solid #000;
+  box-sizing: border-box;
+  padding: 5px 10px;
+}
+.bl {
+  border-left: 2px solid #000;
+}
+
+.bbn {
+  border-bottom: none !important;
+}
+</style>

+ 157 - 0
src/components/tools/sunburst.vue

@@ -0,0 +1,157 @@
+<template>
+  <div class="data_body">
+    <div class="noMind" v-if="mindV">
+      <img src="../../assets/nominddata.png" alt />
+    </div>
+    <!-- <img src="../../assets/dataimage/1.png" style="width:90%" /> -->
+    <div
+      id="charts_canvas"
+      class="echart"
+      style="width: 100%; height: 100%"
+    ></div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: ["Josn", "num"],
+  data() {
+    return {
+      mindV: true,
+      chartObj: null,
+      timer: null,
+      ooption: [],
+      option: {
+        series: {
+          type: "sunburst",
+          data: [],
+          radius: [30, "90%"],
+          label: {
+            rotate: "radial",
+          },
+        },
+      },
+    };
+  },
+  methods: {
+    setChart(option) {
+      // 雷达图显示的标签
+      let newPromise = new Promise((resolve) => {
+        resolve();
+      });
+      //然后异步执行echarts的初始化函数
+      newPromise.then(() => {
+        const chartObj = this.$echarts.init(
+          //劳动课程
+          this.$el.querySelector("#charts_canvas")
+        );
+        this.option.series.data = option;
+        // 初始化雷达图
+        this.chartObj = chartObj;
+        this.chartObj.setOption(this.option);
+      });
+    },
+    setData() {
+      if (!Object.keys(this.Josn).length) {
+        this.mindV = true;
+      } else {
+        this.mindV = false;
+      }
+      var res = this.Josn;
+      var _array = [];
+      let i = 0;
+      for (var item in res) {
+        let num = Object.keys(res);
+        let count = 10 / num.length;
+        let _item = res[item];
+        _array.push({ name: _item.name, value: count, children: [] });
+        let j = 0;
+        for (var item2 in _item.child) {
+          let num2 = Object.keys(res);
+          let count2 = count / num2.length;
+          let _item2 = _item.child[item2];
+          _array[i].children.push({
+            name: _item2.name,
+            value: count2,
+            children: [],
+          });
+          for (var item3 in _item2.child) {
+            let num3 = Object.keys(res);
+            let count3 = count2 / num3.length;
+            let _item3 = _item2.child[item3];
+            _array[i].children[j].children.push({
+              name: _item3.name,
+              value: count3,
+            });
+          }
+          j++;
+        }
+        i++;
+        console.log(item);
+      }
+      this.ooption = _array;
+      if (!this.chartObj) {
+        this.setChart(this.ooption);
+      } else {
+        this.option.series.data = this.ooption;
+        this.chartObj.setOption(this.option);
+      }
+    },
+  },
+  watch: {
+    num: {
+      handler: function (newVal, oldVal) {
+        this.setData();
+      },
+      deep: true,
+    },
+    Josn: {
+      handler: function (newVal, oldVal) {},
+      deep: true,
+    },
+  },
+  mounted() {
+    this.setData();
+    var _this = this;
+    // _this.timer = setInterval(() => {
+    //   if (_this.chartObj) {
+    //     _this.chartObj.resize();
+    //   }
+    // }, 0);
+    // window.addEventListener("resize", () => {
+    //   if (_this.chartObj) {
+    //     _this.chartObj.resize();
+    //   }
+    // });
+  },
+  beforeDestroy() {
+    // clearInterval(this.timer);
+    // this.timer = null
+  },
+};
+</script>
+
+<style scoped>
+.data_body {
+  /* display: flex; */
+  /* flex-direction: column; */
+  width: 500px;
+  height: 450px;
+  /* height: 500px; */
+  /* margin: 15px 5px 0 0; */
+  background: #fff;
+  overflow: hidden;
+  flex-shrink: 0;
+  position: relative;
+}
+.noMind {
+  position: absolute;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+  z-index: 999;
+  background: #fff;
+}
+</style>

+ 1 - 1
src/components/works.vue

@@ -95,7 +95,7 @@ export default {
     return {
       myCourse: [],
       studentMessage: [],
-      tx: require("../assets/tx.png"),
+      tx: require("../assets/avatar.png"),
       mpj: require("../assets/project.png"),
       userid: this.$route.query.userid,
     };

Some files were not shown because too many files changed in this diff