allen 2 年之前
父节点
当前提交
2be633f2eb
共有 38 个文件被更改,包括 4100 次插入18 次删除
  1. 1 1
      public/index.html
  2. 二进制
      public/noun/j20.jpg
  3. 44 0
      src/api/doc/case.js
  4. 44 0
      src/api/doc/radmon.js
  5. 44 0
      src/api/doc/tech.js
  6. 44 0
      src/api/doc/textbook.js
  7. 44 0
      src/api/showInfo/breakdown.js
  8. 1 1
      src/assets/styles/index.scss
  9. 4 0
      src/assets/styles/ruoyi.scss
  10. 5 5
      src/components/Echarts/graph.vue
  11. 13 5
      src/components/TopNav/index.vue
  12. 4 2
      src/router/index.js
  13. 12 0
      src/router/noun/index.js
  14. 343 0
      src/views/ai/question/breakdown/chatMsg.vue
  15. 176 0
      src/views/ai/question/breakdown/index.vue
  16. 1 1
      src/views/ai/question/chatMsg.vue
  17. 340 0
      src/views/ai/question/knowledage/chatMsg.vue
  18. 176 0
      src/views/ai/question/knowledage/index.vue
  19. 343 0
      src/views/ai/question/suggest/chatMsg.vue
  20. 176 0
      src/views/ai/question/suggest/index.vue
  21. 286 0
      src/views/doc/case/index.vue
  22. 286 0
      src/views/doc/radmon/index.vue
  23. 286 0
      src/views/doc/tech/index.vue
  24. 286 0
      src/views/doc/textbook/index.vue
  25. 2 3
      src/views/knowledge/search/index.vue
  26. 31 0
      src/views/knowledge/test/index.vue
  27. 1 0
      src/views/login.vue
  28. 19 0
      src/views/repair/noun/5aircraft.md
  29. 2 0
      src/views/repair/noun/5aircraft.vue
  30. 55 0
      src/views/repair/noun/detail.vue
  31. 40 0
      src/views/repair/noun/index.vue
  32. 58 0
      src/views/repair/noun/test.json
  33. 26 0
      src/views/searchV2/breakdown/index.vue
  34. 26 0
      src/views/searchV2/doc/index.vue
  35. 26 0
      src/views/searchV2/knowledge/index.vue
  36. 446 0
      src/views/showInfo/breakdown/index.vue
  37. 186 0
      src/views/showInfo/breakdown/show/index.vue
  38. 223 0
      src/views/showInfo/breakdown/statistics/index.vue

+ 1 - 1
public/index.html

@@ -12,7 +12,7 @@
     html,
     body,
     #app {
-      height: 100%;
+      /* height: 100%; */
       margin: 0px;
       padding: 0px;
     }

二进制
public/noun/j20.jpg


+ 44 - 0
src/api/doc/case.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询案例列表
+export function listCase(query) {
+  return request({
+    url: '/doc/case/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询案例详细
+export function getCase(id) {
+  return request({
+    url: '/doc/case/' + id,
+    method: 'get'
+  })
+}
+
+// 新增案例
+export function addCase(data) {
+  return request({
+    url: '/doc/case',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改案例
+export function updateCase(data) {
+  return request({
+    url: '/doc/case',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除案例
+export function delCase(id) {
+  return request({
+    url: '/doc/case/' + id,
+    method: 'delete'
+  })
+}

+ 44 - 0
src/api/doc/radmon.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询随机资料列表
+export function listRadmon(query) {
+  return request({
+    url: '/doc/radmon/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询随机资料详细
+export function getRadmon(id) {
+  return request({
+    url: '/doc/radmon/' + id,
+    method: 'get'
+  })
+}
+
+// 新增随机资料
+export function addRadmon(data) {
+  return request({
+    url: '/doc/radmon',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改随机资料
+export function updateRadmon(data) {
+  return request({
+    url: '/doc/radmon',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除随机资料
+export function delRadmon(id) {
+  return request({
+    url: '/doc/radmon/' + id,
+    method: 'delete'
+  })
+}

+ 44 - 0
src/api/doc/tech.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询技术通报列表
+export function listTech(query) {
+  return request({
+    url: '/doc/tech/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询技术通报详细
+export function getTech(id) {
+  return request({
+    url: '/doc/tech/' + id,
+    method: 'get'
+  })
+}
+
+// 新增技术通报
+export function addTech(data) {
+  return request({
+    url: '/doc/tech',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改技术通报
+export function updateTech(data) {
+  return request({
+    url: '/doc/tech',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除技术通报
+export function delTech(id) {
+  return request({
+    url: '/doc/tech/' + id,
+    method: 'delete'
+  })
+}

+ 44 - 0
src/api/doc/textbook.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询教材列表
+export function listTextbook(query) {
+  return request({
+    url: '/doc/textbook/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询教材详细
+export function getTextbook(id) {
+  return request({
+    url: '/doc/textbook/' + id,
+    method: 'get'
+  })
+}
+
+// 新增教材
+export function addTextbook(data) {
+  return request({
+    url: '/doc/textbook',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改教材
+export function updateTextbook(data) {
+  return request({
+    url: '/doc/textbook',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除教材
+export function delTextbook(id) {
+  return request({
+    url: '/doc/textbook/' + id,
+    method: 'delete'
+  })
+}

+ 44 - 0
src/api/showInfo/breakdown.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询故障信息列表
+export function listBreakdown(query) {
+  return request({
+    url: '/showInfo/breakdown/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询故障信息详细
+export function getBreakdown(id) {
+  return request({
+    url: '/showInfo/breakdown/' + id,
+    method: 'get'
+  })
+}
+
+// 新增故障信息
+export function addBreakdown(data) {
+  return request({
+    url: '/showInfo/breakdown',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改故障信息
+export function updateBreakdown(data) {
+  return request({
+    url: '/showInfo/breakdown',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除故障信息
+export function delBreakdown(id) {
+  return request({
+    url: '/showInfo/breakdown/' + id,
+    method: 'delete'
+  })
+}

+ 1 - 1
src/assets/styles/index.scss

@@ -23,7 +23,7 @@ html {
 }
 
 #app {
-  height: 100%;
+  min-height: 100%;
 }
 
 *,

+ 4 - 0
src/assets/styles/ruoyi.scss

@@ -308,3 +308,7 @@
  .el-message-box__title {
 	color: #bfcbd9;
  }
+
+ .el-dialog__body{
+    color: #bfcbd9
+}

+ 5 - 5
src/components/Echarts/graph.vue

@@ -85,7 +85,7 @@ export default {
               normal: {
                 show: true,
                 textStyle: {
-                  fontSize: 12,
+                  fontSize: 16,
                 },
                 position: "middle",
                 formatter: function (x) {
@@ -113,7 +113,7 @@ export default {
                     fontStyle: "normal", //文字字体的风格 'normal'标准 'italic'斜体 'oblique' 倾斜
                     fontWeight: "bold", //'normal'标准'bold'粗的'bolder'更粗的'lighter'更细的或100 | 200 | 300 | 400...
                     fontFamily: "sans-serif", //文字的字体系列
-                    fontSize: 12, //字体大小
+                    fontSize: 16, //字体大小
                   },
                 },
                 nodeStyle: {
@@ -136,7 +136,7 @@ export default {
             label: {
               fontSize: 18,
             },
-            symbolSize: 24, //节点大小
+            symbolSize: 50, //节点大小
             // links: this.seriesLinks,
             edges: this.seriesLinks,
             data: this.seriesData,
@@ -181,7 +181,7 @@ export default {
 </script>
 <style scoped>
 .chart {
-  width: 600px;
-  height: 300px;
+  width: 800px;
+  height: 600px;
 }
 </style>

+ 13 - 5
src/components/TopNav/index.vue

@@ -9,10 +9,10 @@
         ><svg-icon icon-class="nested" />
       检索中心
     </el-menu-item>
-    <el-menu-item :style="{'--theme': theme}" index="/knowledge"
+    <!-- <el-menu-item :style="{'--theme': theme}" index="/knowledge"
         ><svg-icon icon-class="dashboard" />
       知识图谱
-    </el-menu-item>
+    </el-menu-item> -->
     <template v-for="(item, index) in topMenus">
       <!-- <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber"
         ><svg-icon :icon-class="item.meta.icon" /> -->
@@ -40,7 +40,7 @@
 
 <script>
 import { constantRoutes } from "@/router";
-import knowledge from "../../router/knowledge";
+// import knowledge from "../../router/knowledge";
 
 // 隐藏侧边栏路由
 const hideList = ['/index', '/user/profile'];
@@ -51,7 +51,8 @@ export default {
       // 顶部栏初始数
       visibleNumber: 5,
       // 当前激活菜单的 index
-      currentIndex: undefined
+      currentIndex: undefined,
+      isActive: false,
     };
   },
   computed: {
@@ -111,7 +112,10 @@ export default {
         activePath = path;
         this.$store.dispatch('app/toggleSideBarHide', true);
       }
-      this.activeRoutes(activePath);
+      // TODO 菜单卡住bug 20230413 Allen 利用isActive 控制,因为每次点击topNav的时候activeMenu和handleSelect都会执行,所以有时候是sidebar你选择的,有时候是当前路径的
+      if(!this.isActive){
+        this.activeRoutes(activePath);
+      }
       return activePath;
     },
   },
@@ -146,6 +150,10 @@ export default {
         this.activeRoutes(key);
         this.$store.dispatch('app/toggleSideBarHide', false);
       }
+      this.isActive = true;
+      setTimeout( function(){
+        this.isActive = false;
+      }, 100 );
     },
     // 当前激活的路由
     activeRoutes(key) {

+ 4 - 2
src/router/index.js

@@ -6,8 +6,9 @@ Vue.use(Router)
 /* Layout */
 import Layout from '@/layout'
 
-import Knowledge from '@/router/knowledge'
+// import Knowledge from '@/router/knowledge'
 import Search from '@/router/search'
+import Noun from '@/router/noun'
 
 /**
  * Note: 路由配置项
@@ -92,8 +93,9 @@ export const constantRoutes = [
     ]
   },
   // 知识图谱路由
-  ...Knowledge,
+  // ...Knowledge,
   ...Search,
+  ...Noun,
   ]
 
 // 动态路由,基于用户权限动态去加载

+ 12 - 0
src/router/noun/index.js

@@ -0,0 +1,12 @@
+import Noun from '@/views/repair/noun/detail.vue'
+// import {createRouter, createWebHistory} from 'vue-router'
+
+export default  [
+  {
+    path: '/repair/noun/detail',
+    name: 'noun',
+    component: Noun,
+    hidden: true,
+    meta: { title: '名词展示', icon: 'dashboard', activeMenu: '' }
+  }
+]

+ 343 - 0
src/views/ai/question/breakdown/chatMsg.vue

@@ -0,0 +1,343 @@
+<template>
+  <div id="chatmsg" ref="msg">
+    <!-- 动态创建 -->
+    <div v-for="(item, index) in lists" :key="index">
+      <div v-if="item.id == 122" class="user">
+        <div v-scroll>
+          <img :src="item.face" alt />
+          <div class="bubble">
+            <span>{{ item.word }}</span>
+          </div>
+        </div>
+      </div>
+      <div v-if="item.id == 1529" class="touser">
+        <div v-scroll>
+          <img :src="item.face" alt />
+          <div class="tobubble">
+            <span>{{ item.word }}</span
+            >&nbsp;&nbsp;&nbsp;&nbsp;
+            <!-- <template v-if="userinfo.data.answer[1] == item.word">
+              <template v-if="dialogVisible">
+                <el-button @click="hidenGraph(item.graph)">关闭关系图</el-button>
+              </template>
+              <template v-else>
+                <el-button @click="showGraph(item.graph)">显示关系图</el-button>
+              </template>
+            </template> -->
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- graph -->
+    <template v-if="dialogVisible">
+      <el-dialog :visible.sync="dialogVisible">
+        <!-- <chart-comp ref="chart"
+                        @="getInfoTooltip"
+                        :isShowContextMenu="true"
+                        @reloadChart="reloadChart"
+                        :nodes="graph.nodes"
+                        :links="graph.links"
+                        :enable="true"
+                        :isShowChart="true"></chart-comp> -->
+        <Graph ref="charts" :chartList="searchList" />
+      </el-dialog>
+    </template>
+  </div>
+</template>
+
+<script>
+// import { url } from 'inspector';
+
+// import userinfo from "./userinfo";
+import Graph from "@/components/Echarts/graph";
+export default {
+  name: "ChatMsg",
+  components: { Graph },
+  data() {
+    return {
+      userimg: "",
+      lists: [],
+      userinfo: {
+        id: "122",
+        imgurl: require("@/assets/images/user.png"),
+        words: "是的!",
+        data: {
+          id: "1529",
+          imgurl: require("@/assets/images/robot-img.png"),
+          name: "易安居士",
+          answer: {
+            1: "由于过大异物进入,导致油滤失效,最终造成动力不足",
+            2: "机翼、机身、尾翼、起落装置、操纵系统和动力装置",
+            3: "",
+            4: "",
+            5: "",
+            6: "",
+            7: "",
+            8: "",
+            9: "",
+            10: "",
+          },
+        },
+      },
+      graph: {},
+      dialogVisible: false,
+      searchList: {
+        seriesData: [
+          {
+            name: "飞机",
+          },
+          {
+            name: "机翼",
+          },
+          {
+            name: "机身",
+          },
+          {
+            name: "尾翼",
+          },
+          {
+            name: "起落装置",
+          },
+          {
+            name: "操纵系统",
+          },
+          {
+            name: "动力系统",
+          },
+        ],
+        linksData: [
+          {
+            source: "机翼",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "机身",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "尾翼",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "起落装置",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "操纵系统",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "动力系统",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+        ],
+      },
+    };
+  },
+  created() {},
+  mounted() {
+    this.userid = this.userinfo.id;
+    this.userimg = this.userinfo.imgurl;
+  },
+  // vue自动滚动到底部
+  directives: {
+    scroll: {
+      inserted(el) {
+        el.scrollIntoView();
+      },
+    },
+  },
+  methods: {
+    saveMsg(tomsg) {
+      this.lists.push({
+        id: this.userid,
+        face: this.userimg,
+        word: tomsg,
+      });
+    },
+    randomMsg(tomsg) {
+      let touserdata = this.userinfo.data;
+      let answer = "对不起,没找到相关答案";
+      if ("飞机动力不足的原因" == tomsg) {
+        answer = this.userinfo.data.answer["1"];
+      } else if ("飞机的组成" == tomsg) {
+        answer = this.userinfo.data.answer["2"];
+      }
+
+      // let graph = {
+      //   nodes: [
+      //     {
+      //       entClsID: "1",
+      //       id: "1",
+      //       label: "机翼",
+      //       entClsName: "机翼",
+      //     },
+      //     {
+      //       entClsID: "2",
+      //       id: "2",
+      //       label: "机翼2",
+      //       entClsName: "机翼2",
+      //     },
+      //     {
+      //       entClsID: "3",
+      //       id: "3",
+      //       label: "机翼3",
+      //       entClsName: "机翼3",
+      //     },
+      //     {
+      //       entClsID: "4",
+      //       id: "4",
+      //       label: "机翼4",
+      //       entClsName: "机翼4",
+      //     },
+      //     {
+      //       entClsID: "5",
+      //       id: "5",
+      //       label: "机翼5",
+      //       entClsName: "机翼5",
+      //     },
+      //   ],
+      //   links: [{}, {}],
+      // };
+
+      this.lists.push({
+        id: touserdata.id,
+        face: touserdata.imgurl,
+        word: answer,
+      });
+    },
+    showGraph(graph) {
+      this.dialogVisible = true;
+      // this.graph = graph;
+    },
+    hidenGraph() {
+      this.dialogVisible = false;
+    },
+    // reloadChart() {
+    //   this.drawChart(this.graph.nodes, this.graph.links);
+    // },
+    // /**
+    //  * 画图
+    //  * @params nodes: 处理好的实体数据, link: 处理好的关系数据
+    //  * */
+    // drawChart(nodes, links) {
+    //   // this.nodes = nodes
+    //   // this.links = links
+    //   this.$refs.chart.destroyChart(); // 先清空chart实例,再绘图
+    //   this.$refs.chart.reDraw(undefined, nodes, links);
+    // },
+    // getInfoTooltip() {},
+  },
+};
+</script>
+
+<style lang="scss" scope>
+#chatmsg {
+  position: relative;
+  // top: 3.5rem;
+  width: 100%;
+  // min-height: 44rem;
+  height: 400px;
+  // background-color: rgba(238, 212, 238, 0.3);
+  margin-bottom: 3.5rem;
+  overflow-x: hidden;
+  overflow-y: auto;
+  .user {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    margin: 0.8rem 0;
+    img {
+      object-fit: cover;
+      width: 3rem;
+      height: 3rem;
+      border-radius: 3px;
+      float: right;
+      margin-right: 1rem;
+    }
+    .bubble {
+      position: relative;
+      float: right;
+      margin-right: 1rem;
+      padding: 0.8rem;
+      box-sizing: border-box;
+      border-radius: 3px;
+      max-width: 65%;
+      background-color: rgb(116, 228, 116);
+      span {
+        height: 1.25rem;
+        line-height: 1.25rem;
+      }
+    }
+    .bubble::after {
+      position: absolute;
+      right: -1.3rem;
+      top: 0.8rem;
+      content: "";
+      width: 0;
+      height: 0;
+      border: 0.7rem solid;
+      border-color: transparent transparent transparent rgb(116, 228, 116);
+    }
+  }
+  .touser {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    margin: 0.8rem 0;
+    img {
+      object-fit: cover;
+      width: 3rem;
+      height: 3rem;
+      border-radius: 3px;
+      float: left;
+      margin-left: 1rem;
+    }
+    .tobubble {
+      position: relative;
+      float: left;
+      margin-left: 1rem;
+      padding: 0 0.7rem;
+      box-sizing: border-box;
+      border-radius: 3px;
+      max-width: 65%;
+      background-color: rgb(116, 228, 116);
+      line-height: 3rem;
+    }
+    .tobubble::after {
+      position: absolute;
+      left: -1.3rem;
+      top: 0.8rem;
+      content: "";
+      width: 0;
+      height: 0;
+      border: 0.7rem solid;
+      border-color: transparent rgb(116, 228, 116) transparent transparent;
+    }
+  }
+}
+</style>

+ 176 - 0
src/views/ai/question/breakdown/index.vue

@@ -0,0 +1,176 @@
+<template>
+  <div id="chatdetail">
+    <!-- <div class="chattop">
+      <div @click="goback" class="chattop_back">
+        <icon-svg icon-class="houtui_shangyibu_zuojiantou_shangyiye" />
+      </div>
+      <div class="chattop_name">{{ name }}</div>
+      <div class="chattop_more">
+        <icon-svg icon-class="gengduo" />
+      </div>
+    </div> -->
+    <div class="chatcontent">
+        <!-- document.getElementById('chatdetail').clientHeight -->
+      <ChatMsg ref="chatmsg"/>
+    </div>
+    <div id="chatfooter" class="chatfooter">
+      <div @click="changeSound">
+        <icon-svg :icon-class="issound" />
+      </div>
+      <div>
+        <input ref="sendcontent" @keypress="sendmsg" :type="istype" :value="isvalue" />
+      </div>
+      <div>
+        <icon-svg icon-class="biaoqing" />
+      </div>
+      <div>
+        <icon-svg icon-class="del" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import ChatMsg from "./chatMsg";
+export default {
+  name: "ChatDetail",
+  data() {
+    return {
+      name: null,
+      issound: "xiaoxitongzhi",
+      istype: "text",
+      isvalue: "飞机动力不足的原因",
+      isshow: false,
+      tomsg: "",
+      msgchild: null,
+    };
+  },
+  components: {
+    ChatMsg: ChatMsg,
+  },
+  mounted() {
+    this.name = this.$route.query.name;
+    this.msgchild = this.$refs.chatmsg;
+  },
+  methods: {
+    // 进行返回操作
+    goback() {
+      this.$router.go(-1);
+    },
+    // 切换input的类型
+    changeSound() {
+      // 在data中定义一个变量isshow:false,利用this.isshow与!this.isshow进行切换
+      if (!this.isshow) {
+        this.isshow = true;
+        this.issound = "yuyin";
+        this.istype = "button";
+        this.isvalue = "按住 说话";
+      } else {
+        this.isshow = false;
+        this.issound = "xiaoxitongzhi";
+        this.istype = "text";
+        this.isvalue = "";
+      }
+    },
+    // 发送消息
+    sendmsg(e) {
+      // 1、用ref定义输入回复内容的input文本框,定义sendcontent变量接收其value值(输入的内容)
+      let sendcontent = this.$refs.sendcontent.value;
+      if (e.keyCode === 13 && sendcontent.split(" ").join("").length !== 0) {
+        // 2、将ChatDetail(父)组件中的sendcontent(文本框输入的值)先用tomsg接收
+        this.tomsg = sendcontent;
+        // 3、用ref定义ChatMsg(子)组件,并在mounted中使用$refs获取,即this.msgchild
+        // 4、调子组件里的方法,并将tomsg传到ChatMsg(子)组件(具体的聊天内容)中
+        this.msgchild.saveMsg(this.tomsg);
+        // 5、发送完一条信息之后,需清空文本框
+        this.$refs.sendcontent.value = "";
+        // 回车时,调用子组件的随机消息的方法
+        this.msgchild.randomMsg(this.tomsg);
+      }
+    },
+    // chatcontentStyle(){
+    //     debugger;
+    //     let a = 'height : ' + (document.getElementById('chatdetail').clientHeight - document.getElementById('chatfooter').clientHeight)
+    //     console.info("a")
+    //     console.info(a)
+    //     return a;
+    // }
+  },
+};
+</script>
+
+<style lang="scss" scope>
+#chatdetail {
+//   position: relative;
+  background-color: transparent;
+  height: 400px;
+//   .chattop {
+//     position: fixed;
+//     top: 0;
+//     left: 0;
+//     z-index: 10;
+//     width: 100%;
+//     height: 3.5rem;
+//     line-height: 3.5rem;
+//     background-color: transparent;
+//     display: flex;
+//     flex-direction: row;
+//     .chattop_back {
+//       flex: 1;
+//       margin-left: 1rem;
+//     }
+//     .chattop_name {
+//       flex: 20;
+//       text-align: center;
+//     }
+//     .chattop_more {
+//       flex: 1;
+//       margin-right: 1rem;
+//     }
+//   }
+  .chatcontent {
+    width: 100%;
+    // height: 300px;
+  }
+  .chatfooter {
+    margin-left: 15px;
+    position: fixed;
+    left: 0;
+    bottom: 0;
+    z-index: 10;
+    width: 100%;
+    height: 3.5rem;
+    line-height: 3.5rem;
+    text-align: center;
+    background-color: rgba(240, 240, 240,0.3);
+    display: flex;
+    flex-direction: row;
+    div:nth-child(1),
+    div:nth-child(3),
+    div:nth-child(4) {
+      flex: 1;
+      svg {
+        font-size: 1.5rem;
+        margin-top: 0.9rem;
+      }
+    }
+    div:nth-child(2) {
+      flex: 5;
+      input {
+        width: 100%;
+        height: 2.5rem;
+        outline: none;
+        padding-left: 0.5rem;
+        box-sizing: border-box;
+        height: 2.5rem;
+        margin-top: 0.5rem;
+        border-style: none;
+        font-size: 0.9rem;
+        border-radius: 4px;
+        background-color: transparent;
+        color: #000;
+      }
+    }
+  }
+}
+</style>

+ 1 - 1
src/views/ai/question/chatMsg.vue

@@ -16,7 +16,7 @@
           <div class="tobubble">
             <span>{{ item.word }}</span
             >&nbsp;&nbsp;&nbsp;&nbsp;
-            <template v-if="userinfo.data.answer[1] == item.word">
+            <template v-if="userinfo.data.answer[2] == item.word">
               <template v-if="dialogVisible">
                 <el-button @click="hidenGraph(item.graph)">关闭关系图</el-button>
               </template>

+ 340 - 0
src/views/ai/question/knowledage/chatMsg.vue

@@ -0,0 +1,340 @@
+<template>
+  <div id="chatmsg" ref="msg">
+    <!-- 动态创建 -->
+    <div v-for="(item, index) in lists" :key="index">
+      <div v-if="item.id == 122" class="user">
+        <div v-scroll>
+          <img :src="item.face" alt />
+          <div class="bubble">
+            <span>{{ item.word }}</span>
+          </div>
+        </div>
+      </div>
+      <div v-if="item.id == 1529" class="touser">
+        <div v-scroll>
+          <img :src="item.face" alt />
+          <div class="tobubble">
+            <span>{{ item.word }}</span
+            >&nbsp;&nbsp;&nbsp;&nbsp;
+            <template v-if="userinfo.data.answer[1] == item.word">
+              <template v-if="dialogVisible">
+                <el-button @click="hidenGraph(item.graph)">关闭关系图</el-button>
+              </template>
+              <template v-else>
+                <el-button @click="showGraph(item.graph)">显示关系图</el-button>
+              </template>
+            </template>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- graph -->
+    <template v-if="dialogVisible">
+      <el-dialog :visible.sync="dialogVisible">
+        <!-- <chart-comp ref="chart"
+                        @="getInfoTooltip"
+                        :isShowContextMenu="true"
+                        @reloadChart="reloadChart"
+                        :nodes="graph.nodes"
+                        :links="graph.links"
+                        :enable="true"
+                        :isShowChart="true"></chart-comp> -->
+        <Graph ref="charts" :chartList="searchList" />
+      </el-dialog>
+    </template>
+  </div>
+</template>
+
+<script>
+// import { url } from 'inspector';
+
+// import userinfo from "./userinfo";
+import Graph from "@/components/Echarts/graph";
+export default {
+  name: "ChatMsg",
+  components: { Graph },
+  data() {
+    return {
+      userimg: "",
+      lists: [],
+      userinfo: {
+        id: "122",
+        imgurl: require("@/assets/images/user.png"),
+        words: "是的!",
+        data: {
+          id: "1529",
+          imgurl: require("@/assets/images/robot-img.png"),
+          name: "易安居士",
+          answer: {
+            1: "歼20的特点有以下几点:1.隐身性好 2.机动性强 3.稳定性好 4.格斗强悍 5.编队攻击 6.多重任务",
+            2: "机翼、机身、尾翼、起落装置、操纵系统和动力装置",
+            3: "",
+            4: "",
+            5: "",
+            6: "",
+            7: "",
+            8: "",
+            9: "",
+            10: "",
+          },
+        },
+      },
+      graph: {},
+      dialogVisible: false,
+      searchList: {
+        seriesData: [
+          {
+            name: "歼20",
+          },
+          {
+            name: "隐身性好",
+          },
+          {
+            name: "机动性强",
+          },
+          {
+            name: "格斗强悍",
+          },
+          {
+            name: "编队攻击",
+          },
+          {
+            name: "多重任务",
+          },
+        ],
+        linksData: [
+          {
+            source: "隐身性好",
+            target: "歼20",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "特点" // line的文字
+            },
+          },
+          {
+            source: "机动性强",
+            target: "歼20",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "特点" // line的文字
+            },
+          },
+          {
+            source: "稳定性好",
+            target: "歼20",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "特点" // line的文字
+            },
+          },
+          {
+            source: "格斗强悍",
+            target: "歼20",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "特点" // line的文字
+            },
+          },
+          {
+            source: "编队攻击",
+            target: "歼20",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "特点" // line的文字
+            },
+          },
+          {
+            source: "多重任务",
+            target: "歼20",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "特点" // line的文字
+            },
+          },
+        ],
+      },
+    };
+  },
+  created() {},
+  mounted() {
+    this.userid = this.userinfo.id;
+    this.userimg = this.userinfo.imgurl;
+  },
+  // vue自动滚动到底部
+  directives: {
+    scroll: {
+      inserted(el) {
+        el.scrollIntoView();
+      },
+    },
+  },
+  methods: {
+    saveMsg(tomsg) {
+      this.lists.push({
+        id: this.userid,
+        face: this.userimg,
+        word: tomsg,
+      });
+    },
+    randomMsg(tomsg) {
+      let touserdata = this.userinfo.data;
+      let answer = "对不起,没找到相关答案";
+      if ("歼20的特点" == tomsg) {
+        answer = this.userinfo.data.answer["1"];
+      } else if ("飞机的组成" == tomsg) {
+        answer = this.userinfo.data.answer["2"];
+      }
+
+      // let graph = {
+      //   nodes: [
+      //     {
+      //       entClsID: "1",
+      //       id: "1",
+      //       label: "机翼",
+      //       entClsName: "机翼",
+      //     },
+      //     {
+      //       entClsID: "2",
+      //       id: "2",
+      //       label: "机翼2",
+      //       entClsName: "机翼2",
+      //     },
+      //     {
+      //       entClsID: "3",
+      //       id: "3",
+      //       label: "机翼3",
+      //       entClsName: "机翼3",
+      //     },
+      //     {
+      //       entClsID: "4",
+      //       id: "4",
+      //       label: "机翼4",
+      //       entClsName: "机翼4",
+      //     },
+      //     {
+      //       entClsID: "5",
+      //       id: "5",
+      //       label: "机翼5",
+      //       entClsName: "机翼5",
+      //     },
+      //   ],
+      //   links: [{}, {}],
+      // };
+
+      this.lists.push({
+        id: touserdata.id,
+        face: touserdata.imgurl,
+        word: answer,
+      });
+    },
+    showGraph(graph) {
+      this.dialogVisible = true;
+      // this.graph = graph;
+    },
+    hidenGraph() {
+      this.dialogVisible = false;
+    },
+    // reloadChart() {
+    //   this.drawChart(this.graph.nodes, this.graph.links);
+    // },
+    // /**
+    //  * 画图
+    //  * @params nodes: 处理好的实体数据, link: 处理好的关系数据
+    //  * */
+    // drawChart(nodes, links) {
+    //   // this.nodes = nodes
+    //   // this.links = links
+    //   this.$refs.chart.destroyChart(); // 先清空chart实例,再绘图
+    //   this.$refs.chart.reDraw(undefined, nodes, links);
+    // },
+    // getInfoTooltip() {},
+  },
+};
+</script>
+
+<style lang="scss" scope>
+#chatmsg {
+  position: relative;
+  // top: 3.5rem;
+  width: 100%;
+  // min-height: 44rem;
+  height: 400px;
+  // background-color: rgba(238, 212, 238, 0.3);
+  margin-bottom: 3.5rem;
+  overflow-x: hidden;
+  overflow-y: auto;
+  .user {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    margin: 0.8rem 0;
+    img {
+      object-fit: cover;
+      width: 3rem;
+      height: 3rem;
+      border-radius: 3px;
+      float: right;
+      margin-right: 1rem;
+    }
+    .bubble {
+      position: relative;
+      float: right;
+      margin-right: 1rem;
+      padding: 0.8rem;
+      box-sizing: border-box;
+      border-radius: 3px;
+      max-width: 65%;
+      background-color: rgb(116, 228, 116);
+      span {
+        height: 1.25rem;
+        line-height: 1.25rem;
+      }
+    }
+    .bubble::after {
+      position: absolute;
+      right: -1.3rem;
+      top: 0.8rem;
+      content: "";
+      width: 0;
+      height: 0;
+      border: 0.7rem solid;
+      border-color: transparent transparent transparent rgb(116, 228, 116);
+    }
+  }
+  .touser {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    margin: 0.8rem 0;
+    img {
+      object-fit: cover;
+      width: 3rem;
+      height: 3rem;
+      border-radius: 3px;
+      float: left;
+      margin-left: 1rem;
+    }
+    .tobubble {
+      position: relative;
+      float: left;
+      margin-left: 1rem;
+      padding: 0 0.7rem;
+      box-sizing: border-box;
+      border-radius: 3px;
+      max-width: 65%;
+      background-color: rgb(116, 228, 116);
+      line-height: 3rem;
+    }
+    .tobubble::after {
+      position: absolute;
+      left: -1.3rem;
+      top: 0.8rem;
+      content: "";
+      width: 0;
+      height: 0;
+      border: 0.7rem solid;
+      border-color: transparent rgb(116, 228, 116) transparent transparent;
+    }
+  }
+}
+</style>

+ 176 - 0
src/views/ai/question/knowledage/index.vue

@@ -0,0 +1,176 @@
+<template>
+  <div id="chatdetail">
+    <!-- <div class="chattop">
+      <div @click="goback" class="chattop_back">
+        <icon-svg icon-class="houtui_shangyibu_zuojiantou_shangyiye" />
+      </div>
+      <div class="chattop_name">{{ name }}</div>
+      <div class="chattop_more">
+        <icon-svg icon-class="gengduo" />
+      </div>
+    </div> -->
+    <div class="chatcontent">
+        <!-- document.getElementById('chatdetail').clientHeight -->
+      <ChatMsg ref="chatmsg"/>
+    </div>
+    <div id="chatfooter" class="chatfooter">
+      <div @click="changeSound">
+        <icon-svg :icon-class="issound" />
+      </div>
+      <div>
+        <input ref="sendcontent" @keypress="sendmsg" :type="istype" :value="isvalue" />
+      </div>
+      <div>
+        <icon-svg icon-class="biaoqing" />
+      </div>
+      <div>
+        <icon-svg icon-class="del" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import ChatMsg from "./chatMsg";
+export default {
+  name: "ChatDetail",
+  data() {
+    return {
+      name: null,
+      issound: "xiaoxitongzhi",
+      istype: "text",
+      isvalue: "歼20的特点",
+      isshow: false,
+      tomsg: "",
+      msgchild: null,
+    };
+  },
+  components: {
+    ChatMsg: ChatMsg,
+  },
+  mounted() {
+    this.name = this.$route.query.name;
+    this.msgchild = this.$refs.chatmsg;
+  },
+  methods: {
+    // 进行返回操作
+    goback() {
+      this.$router.go(-1);
+    },
+    // 切换input的类型
+    changeSound() {
+      // 在data中定义一个变量isshow:false,利用this.isshow与!this.isshow进行切换
+      if (!this.isshow) {
+        this.isshow = true;
+        this.issound = "yuyin";
+        this.istype = "button";
+        this.isvalue = "按住 说话";
+      } else {
+        this.isshow = false;
+        this.issound = "xiaoxitongzhi";
+        this.istype = "text";
+        this.isvalue = "";
+      }
+    },
+    // 发送消息
+    sendmsg(e) {
+      // 1、用ref定义输入回复内容的input文本框,定义sendcontent变量接收其value值(输入的内容)
+      let sendcontent = this.$refs.sendcontent.value;
+      if (e.keyCode === 13 && sendcontent.split(" ").join("").length !== 0) {
+        // 2、将ChatDetail(父)组件中的sendcontent(文本框输入的值)先用tomsg接收
+        this.tomsg = sendcontent;
+        // 3、用ref定义ChatMsg(子)组件,并在mounted中使用$refs获取,即this.msgchild
+        // 4、调子组件里的方法,并将tomsg传到ChatMsg(子)组件(具体的聊天内容)中
+        this.msgchild.saveMsg(this.tomsg);
+        // 5、发送完一条信息之后,需清空文本框
+        this.$refs.sendcontent.value = "";
+        // 回车时,调用子组件的随机消息的方法
+        this.msgchild.randomMsg(this.tomsg);
+      }
+    },
+    // chatcontentStyle(){
+    //     debugger;
+    //     let a = 'height : ' + (document.getElementById('chatdetail').clientHeight - document.getElementById('chatfooter').clientHeight)
+    //     console.info("a")
+    //     console.info(a)
+    //     return a;
+    // }
+  },
+};
+</script>
+
+<style lang="scss" scope>
+#chatdetail {
+//   position: relative;
+  background-color: transparent;
+  height: 400px;
+//   .chattop {
+//     position: fixed;
+//     top: 0;
+//     left: 0;
+//     z-index: 10;
+//     width: 100%;
+//     height: 3.5rem;
+//     line-height: 3.5rem;
+//     background-color: transparent;
+//     display: flex;
+//     flex-direction: row;
+//     .chattop_back {
+//       flex: 1;
+//       margin-left: 1rem;
+//     }
+//     .chattop_name {
+//       flex: 20;
+//       text-align: center;
+//     }
+//     .chattop_more {
+//       flex: 1;
+//       margin-right: 1rem;
+//     }
+//   }
+  .chatcontent {
+    width: 100%;
+    // height: 300px;
+  }
+  .chatfooter {
+    margin-left: 15px;
+    position: fixed;
+    left: 0;
+    bottom: 0;
+    z-index: 10;
+    width: 100%;
+    height: 3.5rem;
+    line-height: 3.5rem;
+    text-align: center;
+    background-color: rgba(240, 240, 240,0.3);
+    display: flex;
+    flex-direction: row;
+    div:nth-child(1),
+    div:nth-child(3),
+    div:nth-child(4) {
+      flex: 1;
+      svg {
+        font-size: 1.5rem;
+        margin-top: 0.9rem;
+      }
+    }
+    div:nth-child(2) {
+      flex: 5;
+      input {
+        width: 100%;
+        height: 2.5rem;
+        outline: none;
+        padding-left: 0.5rem;
+        box-sizing: border-box;
+        height: 2.5rem;
+        margin-top: 0.5rem;
+        border-style: none;
+        font-size: 0.9rem;
+        border-radius: 4px;
+        background-color: transparent;
+        color: #000;
+      }
+    }
+  }
+}
+</style>

+ 343 - 0
src/views/ai/question/suggest/chatMsg.vue

@@ -0,0 +1,343 @@
+<template>
+  <div id="chatmsg" ref="msg">
+    <!-- 动态创建 -->
+    <div v-for="(item, index) in lists" :key="index">
+      <div v-if="item.id == 122" class="user">
+        <div v-scroll>
+          <img :src="item.face" alt />
+          <div class="bubble">
+            <span>{{ item.word }}</span>
+          </div>
+        </div>
+      </div>
+      <div v-if="item.id == 1529" class="touser">
+        <div v-scroll>
+          <img :src="item.face" alt />
+          <div class="tobubble">
+            <span>{{ item.word }}</span
+            >&nbsp;&nbsp;&nbsp;&nbsp;
+            <!-- <template v-if="userinfo.data.answer[1] == item.word">
+              <template v-if="dialogVisible">
+                <el-button @click="hidenGraph(item.graph)">关闭关系图</el-button>
+              </template>
+              <template v-else>
+                <el-button @click="showGraph(item.graph)">显示关系图</el-button>
+              </template>
+            </template> -->
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- graph -->
+    <template v-if="dialogVisible">
+      <el-dialog :visible.sync="dialogVisible">
+        <!-- <chart-comp ref="chart"
+                        @="getInfoTooltip"
+                        :isShowContextMenu="true"
+                        @reloadChart="reloadChart"
+                        :nodes="graph.nodes"
+                        :links="graph.links"
+                        :enable="true"
+                        :isShowChart="true"></chart-comp> -->
+        <Graph ref="charts" :chartList="searchList" />
+      </el-dialog>
+    </template>
+  </div>
+</template>
+
+<script>
+// import { url } from 'inspector';
+
+// import userinfo from "./userinfo";
+import Graph from "@/components/Echarts/graph";
+export default {
+  name: "ChatMsg",
+  components: { Graph },
+  data() {
+    return {
+      userimg: "",
+      lists: [],
+      userinfo: {
+        id: "122",
+        imgurl: require("@/assets/images/user.png"),
+        words: "是的!",
+        data: {
+          id: "1529",
+          imgurl: require("@/assets/images/robot-img.png"),
+          name: "易安居士",
+          answer: {
+            1: "歼击机,强击机,轰炸机,侦察机,运输机,预警机,电子干扰机、反潜机、教练机、空中加油机、舰载飞机等等",
+            2: "机翼、机身、尾翼、起落装置、操纵系统和动力装置",
+            3: "",
+            4: "",
+            5: "",
+            6: "",
+            7: "",
+            8: "",
+            9: "",
+            10: "",
+          },
+        },
+      },
+      graph: {},
+      dialogVisible: false,
+      searchList: {
+        seriesData: [
+          {
+            name: "飞机",
+          },
+          {
+            name: "机翼",
+          },
+          {
+            name: "机身",
+          },
+          {
+            name: "尾翼",
+          },
+          {
+            name: "起落装置",
+          },
+          {
+            name: "操纵系统",
+          },
+          {
+            name: "动力系统",
+          },
+        ],
+        linksData: [
+          {
+            source: "机翼",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "机身",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "尾翼",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "起落装置",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "操纵系统",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+          {
+            source: "动力系统",
+            target: "飞机",
+            label: {
+              show: true, // 是否显示line的文字
+              formatter: "组成" // line的文字
+            },
+          },
+        ],
+      },
+    };
+  },
+  created() {},
+  mounted() {
+    this.userid = this.userinfo.id;
+    this.userimg = this.userinfo.imgurl;
+  },
+  // vue自动滚动到底部
+  directives: {
+    scroll: {
+      inserted(el) {
+        el.scrollIntoView();
+      },
+    },
+  },
+  methods: {
+    saveMsg(tomsg) {
+      this.lists.push({
+        id: this.userid,
+        face: this.userimg,
+        word: tomsg,
+      });
+    },
+    randomMsg(tomsg) {
+      let touserdata = this.userinfo.data;
+      let answer = "对不起,没找到相关答案";
+      if ("飞机的种类" == tomsg) {
+        answer = this.userinfo.data.answer["1"];
+      } else if ("飞机的组成" == tomsg) {
+        answer = this.userinfo.data.answer["2"];
+      }
+
+      // let graph = {
+      //   nodes: [
+      //     {
+      //       entClsID: "1",
+      //       id: "1",
+      //       label: "机翼",
+      //       entClsName: "机翼",
+      //     },
+      //     {
+      //       entClsID: "2",
+      //       id: "2",
+      //       label: "机翼2",
+      //       entClsName: "机翼2",
+      //     },
+      //     {
+      //       entClsID: "3",
+      //       id: "3",
+      //       label: "机翼3",
+      //       entClsName: "机翼3",
+      //     },
+      //     {
+      //       entClsID: "4",
+      //       id: "4",
+      //       label: "机翼4",
+      //       entClsName: "机翼4",
+      //     },
+      //     {
+      //       entClsID: "5",
+      //       id: "5",
+      //       label: "机翼5",
+      //       entClsName: "机翼5",
+      //     },
+      //   ],
+      //   links: [{}, {}],
+      // };
+
+      this.lists.push({
+        id: touserdata.id,
+        face: touserdata.imgurl,
+        word: answer,
+      });
+    },
+    showGraph(graph) {
+      this.dialogVisible = true;
+      // this.graph = graph;
+    },
+    hidenGraph() {
+      this.dialogVisible = false;
+    },
+    // reloadChart() {
+    //   this.drawChart(this.graph.nodes, this.graph.links);
+    // },
+    // /**
+    //  * 画图
+    //  * @params nodes: 处理好的实体数据, link: 处理好的关系数据
+    //  * */
+    // drawChart(nodes, links) {
+    //   // this.nodes = nodes
+    //   // this.links = links
+    //   this.$refs.chart.destroyChart(); // 先清空chart实例,再绘图
+    //   this.$refs.chart.reDraw(undefined, nodes, links);
+    // },
+    // getInfoTooltip() {},
+  },
+};
+</script>
+
+<style lang="scss" scope>
+#chatmsg {
+  position: relative;
+  // top: 3.5rem;
+  width: 100%;
+  // min-height: 44rem;
+  height: 400px;
+  // background-color: rgba(238, 212, 238, 0.3);
+  margin-bottom: 3.5rem;
+  overflow-x: hidden;
+  overflow-y: auto;
+  .user {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    margin: 0.8rem 0;
+    img {
+      object-fit: cover;
+      width: 3rem;
+      height: 3rem;
+      border-radius: 3px;
+      float: right;
+      margin-right: 1rem;
+    }
+    .bubble {
+      position: relative;
+      float: right;
+      margin-right: 1rem;
+      padding: 0.8rem;
+      box-sizing: border-box;
+      border-radius: 3px;
+      max-width: 65%;
+      background-color: rgb(116, 228, 116);
+      span {
+        height: 1.25rem;
+        line-height: 1.25rem;
+      }
+    }
+    .bubble::after {
+      position: absolute;
+      right: -1.3rem;
+      top: 0.8rem;
+      content: "";
+      width: 0;
+      height: 0;
+      border: 0.7rem solid;
+      border-color: transparent transparent transparent rgb(116, 228, 116);
+    }
+  }
+  .touser {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    margin: 0.8rem 0;
+    img {
+      object-fit: cover;
+      width: 3rem;
+      height: 3rem;
+      border-radius: 3px;
+      float: left;
+      margin-left: 1rem;
+    }
+    .tobubble {
+      position: relative;
+      float: left;
+      margin-left: 1rem;
+      padding: 0 0.7rem;
+      box-sizing: border-box;
+      border-radius: 3px;
+      max-width: 65%;
+      background-color: rgb(116, 228, 116);
+      line-height: 3rem;
+    }
+    .tobubble::after {
+      position: absolute;
+      left: -1.3rem;
+      top: 0.8rem;
+      content: "";
+      width: 0;
+      height: 0;
+      border: 0.7rem solid;
+      border-color: transparent rgb(116, 228, 116) transparent transparent;
+    }
+  }
+}
+</style>

+ 176 - 0
src/views/ai/question/suggest/index.vue

@@ -0,0 +1,176 @@
+<template>
+  <div id="chatdetail">
+    <!-- <div class="chattop">
+      <div @click="goback" class="chattop_back">
+        <icon-svg icon-class="houtui_shangyibu_zuojiantou_shangyiye" />
+      </div>
+      <div class="chattop_name">{{ name }}</div>
+      <div class="chattop_more">
+        <icon-svg icon-class="gengduo" />
+      </div>
+    </div> -->
+    <div class="chatcontent">
+        <!-- document.getElementById('chatdetail').clientHeight -->
+      <ChatMsg ref="chatmsg"/>
+    </div>
+    <div id="chatfooter" class="chatfooter">
+      <div @click="changeSound">
+        <icon-svg :icon-class="issound" />
+      </div>
+      <div>
+        <input ref="sendcontent" @keypress="sendmsg" :type="istype" :value="isvalue" />
+      </div>
+      <div>
+        <icon-svg icon-class="biaoqing" />
+      </div>
+      <div>
+        <icon-svg icon-class="del" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import ChatMsg from "./chatMsg";
+export default {
+  name: "ChatDetail",
+  data() {
+    return {
+      name: null,
+      issound: "xiaoxitongzhi",
+      istype: "text",
+      isvalue: "歼20发动机维修建议",
+      isshow: false,
+      tomsg: "",
+      msgchild: null,
+    };
+  },
+  components: {
+    ChatMsg: ChatMsg,
+  },
+  mounted() {
+    this.name = this.$route.query.name;
+    this.msgchild = this.$refs.chatmsg;
+  },
+  methods: {
+    // 进行返回操作
+    goback() {
+      this.$router.go(-1);
+    },
+    // 切换input的类型
+    changeSound() {
+      // 在data中定义一个变量isshow:false,利用this.isshow与!this.isshow进行切换
+      if (!this.isshow) {
+        this.isshow = true;
+        this.issound = "yuyin";
+        this.istype = "button";
+        this.isvalue = "按住 说话";
+      } else {
+        this.isshow = false;
+        this.issound = "xiaoxitongzhi";
+        this.istype = "text";
+        this.isvalue = "";
+      }
+    },
+    // 发送消息
+    sendmsg(e) {
+      // 1、用ref定义输入回复内容的input文本框,定义sendcontent变量接收其value值(输入的内容)
+      let sendcontent = this.$refs.sendcontent.value;
+      if (e.keyCode === 13 && sendcontent.split(" ").join("").length !== 0) {
+        // 2、将ChatDetail(父)组件中的sendcontent(文本框输入的值)先用tomsg接收
+        this.tomsg = sendcontent;
+        // 3、用ref定义ChatMsg(子)组件,并在mounted中使用$refs获取,即this.msgchild
+        // 4、调子组件里的方法,并将tomsg传到ChatMsg(子)组件(具体的聊天内容)中
+        this.msgchild.saveMsg(this.tomsg);
+        // 5、发送完一条信息之后,需清空文本框
+        this.$refs.sendcontent.value = "";
+        // 回车时,调用子组件的随机消息的方法
+        this.msgchild.randomMsg(this.tomsg);
+      }
+    },
+    // chatcontentStyle(){
+    //     debugger;
+    //     let a = 'height : ' + (document.getElementById('chatdetail').clientHeight - document.getElementById('chatfooter').clientHeight)
+    //     console.info("a")
+    //     console.info(a)
+    //     return a;
+    // }
+  },
+};
+</script>
+
+<style lang="scss" scope>
+#chatdetail {
+//   position: relative;
+  background-color: transparent;
+  height: 400px;
+//   .chattop {
+//     position: fixed;
+//     top: 0;
+//     left: 0;
+//     z-index: 10;
+//     width: 100%;
+//     height: 3.5rem;
+//     line-height: 3.5rem;
+//     background-color: transparent;
+//     display: flex;
+//     flex-direction: row;
+//     .chattop_back {
+//       flex: 1;
+//       margin-left: 1rem;
+//     }
+//     .chattop_name {
+//       flex: 20;
+//       text-align: center;
+//     }
+//     .chattop_more {
+//       flex: 1;
+//       margin-right: 1rem;
+//     }
+//   }
+  .chatcontent {
+    width: 100%;
+    // height: 300px;
+  }
+  .chatfooter {
+    margin-left: 15px;
+    position: fixed;
+    left: 0;
+    bottom: 0;
+    z-index: 10;
+    width: 100%;
+    height: 3.5rem;
+    line-height: 3.5rem;
+    text-align: center;
+    background-color: rgba(240, 240, 240,0.3);
+    display: flex;
+    flex-direction: row;
+    div:nth-child(1),
+    div:nth-child(3),
+    div:nth-child(4) {
+      flex: 1;
+      svg {
+        font-size: 1.5rem;
+        margin-top: 0.9rem;
+      }
+    }
+    div:nth-child(2) {
+      flex: 5;
+      input {
+        width: 100%;
+        height: 2.5rem;
+        outline: none;
+        padding-left: 0.5rem;
+        box-sizing: border-box;
+        height: 2.5rem;
+        margin-top: 0.5rem;
+        border-style: none;
+        font-size: 0.9rem;
+        border-radius: 4px;
+        background-color: transparent;
+        color: #000;
+      }
+    }
+  }
+}
+</style>

+ 286 - 0
src/views/doc/case/index.vue

@@ -0,0 +1,286 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="描述" prop="describe">
+        <el-input
+          v-model="queryParams.describe"
+          placeholder="请输入描述"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['doc:case:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['doc:case:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['doc:case:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['doc:case:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="caseList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号" align="center" prop="id" />
+      <el-table-column label="名称" align="center" prop="name" />
+      <el-table-column label="描述" align="center" prop="describe" />
+      <el-table-column label="类型" align="center" prop="type" />
+      <el-table-column label="文件" align="center" prop="filePath" >
+        <template slot-scope="scope">
+          <el-link :href="`${baseUrl}${scope.row.filePath}`" :underline="false" target="_blank">
+            <span class="el-icon-document"> {{ getFileName(scope.row.filePath) }} </span>
+          </el-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['doc:case:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['doc:case:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改案例对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="描述" prop="describe">
+          <el-input v-model="form.describe" placeholder="请输入描述" />
+        </el-form-item>
+        <el-form-item label="文件">
+          <file-upload v-model="form.filePath"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listCase, getCase, delCase, addCase, updateCase } from "@/api/doc/case";
+
+export default {
+  name: "Case",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 案例表格数据
+      caseList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      },
+      baseUrl: process.env.VUE_APP_BASE_API,
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询案例列表 */
+    getList() {
+      this.loading = true;
+      listCase(this.queryParams).then(response => {
+        this.caseList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加案例";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getCase(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改案例";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateCase(this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addCase(this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除案例编号为"' + ids + '"的数据项?').then(function() {
+        return delCase(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('doc/case/export', {
+        ...this.queryParams
+      }, `case_${new Date().getTime()}.xlsx`)
+    },
+    getFileName(name) {
+      if (name.lastIndexOf("/") > -1) {
+        return name.slice(name.lastIndexOf("/") + 1);
+      } else {
+        return "";
+      }
+    },
+  }
+};
+</script>

+ 286 - 0
src/views/doc/radmon/index.vue

@@ -0,0 +1,286 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="描述" prop="describe">
+        <el-input
+          v-model="queryParams.describe"
+          placeholder="请输入描述"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['doc:radmon:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['doc:radmon:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['doc:radmon:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['doc:radmon:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="radmonList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号" align="center" prop="id" />
+      <el-table-column label="名称" align="center" prop="name" />
+      <el-table-column label="描述" align="center" prop="describe" />
+      <el-table-column label="类型" align="center" prop="type" />
+      <el-table-column label="文件" align="center" prop="filePath" >
+        <template slot-scope="scope">
+          <el-link :href="`${baseUrl}${scope.row.filePath}`" :underline="false" target="_blank">
+            <span class="el-icon-document"> {{ getFileName(scope.row.filePath) }} </span>
+          </el-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['doc:radmon:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['doc:radmon:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改随机资料对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="描述" prop="describe">
+          <el-input v-model="form.describe" placeholder="请输入描述" />
+        </el-form-item>
+        <el-form-item label="文件">
+          <file-upload v-model="form.filePath"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRadmon, getRadmon, delRadmon, addRadmon, updateRadmon } from "@/api/doc/radmon";
+
+export default {
+  name: "Radmon",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 随机资料表格数据
+      radmonList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      },
+      baseUrl: process.env.VUE_APP_BASE_API,
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询随机资料列表 */
+    getList() {
+      this.loading = true;
+      listRadmon(this.queryParams).then(response => {
+        this.radmonList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加随机资料";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getRadmon(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改随机资料";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateRadmon(this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addRadmon(this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除随机资料编号为"' + ids + '"的数据项?').then(function() {
+        return delRadmon(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('doc/radmon/export', {
+        ...this.queryParams
+      }, `radmon_${new Date().getTime()}.xlsx`)
+    },
+    getFileName(name) {
+      if (name.lastIndexOf("/") > -1) {
+        return name.slice(name.lastIndexOf("/") + 1);
+      } else {
+        return "";
+      }
+    },
+  }
+};
+</script>

+ 286 - 0
src/views/doc/tech/index.vue

@@ -0,0 +1,286 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="描述" prop="describe">
+        <el-input
+          v-model="queryParams.describe"
+          placeholder="请输入描述"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['doc:tech:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['doc:tech:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['doc:tech:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['doc:tech:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="techList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号" align="center" prop="id" />
+      <el-table-column label="名称" align="center" prop="name" />
+      <el-table-column label="描述" align="center" prop="describe" />
+      <el-table-column label="类型" align="center" prop="type" />
+      <el-table-column label="文件" align="center" prop="filePath" >
+        <template slot-scope="scope">
+          <el-link :href="`${baseUrl}${scope.row.filePath}`" :underline="false" target="_blank">
+            <span class="el-icon-document"> {{ getFileName(scope.row.filePath) }} </span>
+          </el-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['doc:tech:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['doc:tech:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改技术通报对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="描述" prop="describe">
+          <el-input v-model="form.describe" placeholder="请输入描述" />
+        </el-form-item>
+        <el-form-item label="文件">
+          <file-upload v-model="form.filePath"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listTech, getTech, delTech, addTech, updateTech } from "@/api/doc/tech";
+
+export default {
+  name: "Tech",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 技术通报表格数据
+      techList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      },
+      baseUrl: process.env.VUE_APP_BASE_API,
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询技术通报列表 */
+    getList() {
+      this.loading = true;
+      listTech(this.queryParams).then(response => {
+        this.techList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加技术通报";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getTech(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改技术通报";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateTech(this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addTech(this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除技术通报编号为"' + ids + '"的数据项?').then(function() {
+        return delTech(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('doc/tech/export', {
+        ...this.queryParams
+      }, `tech_${new Date().getTime()}.xlsx`)
+    },
+    getFileName(name) {
+      if (name.lastIndexOf("/") > -1) {
+        return name.slice(name.lastIndexOf("/") + 1);
+      } else {
+        return "";
+      }
+    },
+  }
+};
+</script>

+ 286 - 0
src/views/doc/textbook/index.vue

@@ -0,0 +1,286 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="描述" prop="describe">
+        <el-input
+          v-model="queryParams.describe"
+          placeholder="请输入描述"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['doc:textbook:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['doc:textbook:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['doc:textbook:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['doc:textbook:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="textbookList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号" align="center" prop="id" />
+      <el-table-column label="名称" align="center" prop="name" />
+      <el-table-column label="描述" align="center" prop="describe" />
+      <el-table-column label="类型" align="center" prop="type" />
+      <el-table-column label="文件" align="center" prop="filePath" >
+        <template slot-scope="scope">
+          <el-link :href="`${baseUrl}${scope.row.filePath}`" :underline="false" target="_blank">
+            <span class="el-icon-document"> {{ getFileName(scope.row.filePath) }} </span>
+          </el-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['doc:textbook:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['doc:textbook:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改教材对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="描述" prop="describe">
+          <el-input v-model="form.describe" placeholder="请输入描述" />
+        </el-form-item>
+        <el-form-item label="文件">
+          <file-upload v-model="form.filePath"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listTextbook, getTextbook, delTextbook, addTextbook, updateTextbook } from "@/api/doc/textbook";
+
+export default {
+  name: "Textbook",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 教材表格数据
+      textbookList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      },
+      baseUrl: process.env.VUE_APP_BASE_API,
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询教材列表 */
+    getList() {
+      this.loading = true;
+      listTextbook(this.queryParams).then(response => {
+        this.textbookList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        name: null,
+        describe: null,
+        type: null,
+        filePath: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加教材";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getTextbook(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改教材";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateTextbook(this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addTextbook(this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除教材编号为"' + ids + '"的数据项?').then(function() {
+        return delTextbook(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('doc/textbook/export', {
+        ...this.queryParams
+      }, `textbook_${new Date().getTime()}.xlsx`)
+    },
+    getFileName(name) {
+      if (name.lastIndexOf("/") > -1) {
+        return name.slice(name.lastIndexOf("/") + 1);
+      } else {
+        return "";
+      }
+    },
+  }
+};
+</script>

+ 2 - 3
src/views/knowledge/search/index.vue

@@ -90,8 +90,8 @@ export default {
   data() {
     return {
       queryParams: {
-        firstName: "转向机",
-        secondName: "转向轴",
+        firstName: "",
+        secondName: "",
         length: "0",
       },
       nodes: [],
@@ -108,7 +108,6 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
-      alert("clear");
     },
     /**
      * 点击搜索重新绘图

+ 31 - 0
src/views/knowledge/test/index.vue

@@ -0,0 +1,31 @@
+<template>
+    <div>
+        <pdf-preview v-if="srcPrint != ''" ref="pdfSearch" :src="srcPrint" @printAlert="printAlert"></pdf-preview>
+    </div>
+</template>
+   
+<script>
+import PdfPreview from 'vue-pdf';
+export default {
+    components: {
+        PdfPreview,
+    },
+    data() {
+        return {
+            srcPrint: 'http://localhost:11082/upload/uploadManage/download?filePath=/profile/upload/2023/04/10/example_20230410144414A001.pdf'
+        }
+    },
+    mounted() {
+        //打开pdf预览窗口
+        this.$refs.pdfSearch.handleOpen();
+    },
+    methods: {
+        printAlert() {//pdf预览窗口点击关闭
+            this.$message.success("打印窗口关闭~");
+        }
+    }
+}
+
+</script>
+   
+<style></style>

+ 1 - 0
src/views/login.vue

@@ -171,6 +171,7 @@ export default {
 }
 
 .login-form {
+  margin-top: 15%;
   border-radius: 6px;
   background: rgba(255,255,255, 0.2);
   width: 400px;

+ 19 - 0
src/views/repair/noun/5aircraft.md

@@ -0,0 +1,19 @@
+# 第五代战斗机
+
+世界现役机种最先进战斗机
+
+第五代战斗机是依照军事上对喷气式战斗机的划代标准,世界现役机种最先进的一代战斗机。第五代战斗机的性能特点一般可以用4S来概括。
+
+第五代战斗机较前一代战斗机最大的特点就是第五代航空发动机的使用以及低可侦测性技术的全面运用,并具备高机动性、先进航电系统、高度集成计算机网络,具备优异的战场状况感知能力以及信息融合能力。服役的第五代战斗机有美国洛克希德·马丁公司生产的F-22、F-35,以及中国的成飞设计并生产的歼-20,另外还有俄罗斯联合飞机集团-苏霍伊公司的苏-57战斗机。
+
+## 战机特点
+
+第五代战斗机需要具备4s的性能特点,即:Stealth(隐形);Super Sonic Cruise(超音速巡航能力);Super Maneuverability(超机动能力);Superior Avionics for Battle Awareness and Effectiveness(超级信息优势),其中在早期美国的F-117A时代具备革命性的就是隐身性能。隐身性能依赖于外形、材料和内部武器舱,即使是装备完全的作战配置,战斗机依然只有非常低的雷达反射截面积。美国的第五代战斗机利用了此前为F-117A、B-2轰炸机和AGM-129“先进巡航导弹”所发展的隐身技术。对于那些单纯凭借机动性取胜的战斗机,这种几乎看不见的作战能力决定了第五代战斗机平台发展中最为重要的革命性部分。
+
+## 设计发展
+
+上一代隐形飞机,如B-2幽灵轰炸机和F-117夜鹰战斗机,由于缺乏电子扫描阵列雷达和LPI无线网络技术,仅限于攻击地面目标。因为使用雷达锁定其他飞机会暴露自己。
+
+20世纪80年代末,苏联提出研制下一代战机以取代服役中的第四代战斗机——米格-29和苏-27的需求。而雅克夫列夫设计局也研制出了雅克-141垂直起降战斗机、雅克-43垂直起降战斗机、雅克-201垂直起降战斗机由于缺乏武器研发资金导致项目取消。以及米格1.44和苏霍伊S-37两种验证机,后因苏联解体而告终 [10] 。2002年,苏霍伊带领设计新型飞机,作为美国F-22和F-35的直接竞争对手。2010年1月29日,苏霍伊集团的苏-57重型战斗机进行了首次试飞,米格集团又开发LMFS战斗机、FGFA战斗机用于出口各国和印度,而印度也在研发AMCA先进中型战斗机。
+
+中国的歼-31,是中国沈阳飞机公司正在研制中的双发单座中型第五代战斗机,于2012年10月31日完成首次飞行测试,其外观具有典型的隐形战机特征,因为采用双前轮起落架,所以有猜测极有可能衍生出可以用于中国航空母舰上的舰载型。

文件差异内容过多而无法显示
+ 2 - 0
src/views/repair/noun/5aircraft.vue


文件差异内容过多而无法显示
+ 55 - 0
src/views/repair/noun/detail.vue


文件差异内容过多而无法显示
+ 40 - 0
src/views/repair/noun/index.vue


+ 58 - 0
src/views/repair/noun/test.json

@@ -0,0 +1,58 @@
+{
+    "msg": "操作成功",
+    "code": 200,
+    "data": {
+        "data": [
+            {
+                "id": 5141,
+                "name": "转向机",
+                "content": null,
+                "attachmentUrl": null,
+                "entClsID": 5141,
+                "entId": 5141,
+                "entName": "转向机",
+                "label": "转向机"
+            },
+            {
+                "id": 5139,
+                "name": "有“咯噔”声",
+                "content": null,
+                "attachmentUrl": null,
+                "entClsID": 5139,
+                "entId": 5139,
+                "entName": "有“咯噔”声",
+                "label": "有“咯噔”声"
+            },
+            {
+                "id": 5142,
+                "name": "转向轴",
+                "content": null,
+                "attachmentUrl": null,
+                "entClsID": 5142,
+                "entId": 5142,
+                "entName": "转向轴",
+                "label": "转向轴"
+            }
+        ],
+        "links": [
+            {
+                "id": 21955,
+                "name": "检测工具",
+                "content": null,
+                "from": 5141,
+                "to": 5139,
+                "relClsName": "检测工具",
+                "relID": 21955
+            },
+            {
+                "id": 21895,
+                "name": "检测工具",
+                "content": null,
+                "from": 5142,
+                "to": 5139,
+                "relClsName": "检测工具",
+                "relID": 21895
+            }
+        ]
+    }
+}

+ 26 - 0
src/views/searchV2/breakdown/index.vue

@@ -0,0 +1,26 @@
+<template>
+    <div class="app-container">
+        <el-row class="margin20">
+            <el-col :span="6"><div>搜索</div></el-col>
+            <el-col :span="12">
+                    <el-input v-model="keyword" placeholder="搜索关键字" suffix-icon="el-icon-search"
+                        @keyup.enter.native="search"></el-input>
+            </el-col>
+        </el-row>
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            keyword: '',
+        }
+    },
+    methods:{
+        search() {
+            console.log(`搜索关键字:${this.keyword}`);
+            // 在此处编写搜索逻辑
+        },
+    },
+}
+</script>

+ 26 - 0
src/views/searchV2/doc/index.vue

@@ -0,0 +1,26 @@
+<template>
+    <div class="app-container">
+        <el-row class="margin20">
+            <el-col :span="6"><div>搜索</div></el-col>
+            <el-col :span="12">
+                    <el-input v-model="keyword" placeholder="搜索关键字" suffix-icon="el-icon-search"
+                        @keyup.enter.native="search"></el-input>
+            </el-col>
+        </el-row>
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            keyword: '',
+        }
+    },
+    methods:{
+        search() {
+            console.log(`搜索关键字:${this.keyword}`);
+            // 在此处编写搜索逻辑
+        },
+    },
+}
+</script>

+ 26 - 0
src/views/searchV2/knowledge/index.vue

@@ -0,0 +1,26 @@
+<template>
+    <div class="app-container">
+        <el-row class="margin20">
+            <el-col :span="6"><div>搜索</div></el-col>
+            <el-col :span="12">
+                    <el-input v-model="keyword" placeholder="搜索关键字" suffix-icon="el-icon-search"
+                        @keyup.enter.native="search"></el-input>
+            </el-col>
+        </el-row>
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            keyword: '',
+        }
+    },
+    methods:{
+        search() {
+            console.log(`搜索关键字:${this.keyword}`);
+            // 在此处编写搜索逻辑
+        },
+    },
+}
+</script>

+ 446 - 0
src/views/showInfo/breakdown/index.vue

@@ -0,0 +1,446 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="战区" prop="warZone">
+        <el-input
+          v-model="queryParams.warZone"
+          placeholder="请输入战区"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="单位" prop="organization">
+        <el-input
+          v-model="queryParams.organization"
+          placeholder="请输入单位"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="发现时机" prop="discoveryTiming">
+        <el-input
+          v-model="queryParams.discoveryTiming"
+          placeholder="请输入发现时机"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="专业" prop="major">
+        <el-input
+          v-model="queryParams.major"
+          placeholder="请输入专业"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障描述" prop="describe">
+        <el-input
+          v-model="queryParams.describe"
+          placeholder="请输入故障描述"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障原因" prop="reason">
+        <el-input
+          v-model="queryParams.reason"
+          placeholder="请输入故障原因"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障件名称" prop="unitName">
+        <el-input
+          v-model="queryParams.unitName"
+          placeholder="请输入故障件名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障件所属系统" prop="unitSystem">
+        <el-input
+          v-model="queryParams.unitSystem"
+          placeholder="请输入故障件所属系统"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障后果" prop="consequence">
+        <el-input
+          v-model="queryParams.consequence"
+          placeholder="请输入故障后果"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障责任" prop="duty">
+        <el-input
+          v-model="queryParams.duty"
+          placeholder="请输入故障责任"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障件名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入故障件名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障件号码" prop="number">
+        <el-input
+          v-model="queryParams.number"
+          placeholder="请输入故障件号码"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="排除方法" prop="method">
+        <el-input
+          v-model="queryParams.method"
+          placeholder="请输入排除方法"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="故障修复时间" prop="repairTime">
+        <el-date-picker clearable
+          v-model="queryParams.repairTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="请选择故障修复时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['showInfo:breakdown:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['showInfo:breakdown:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['showInfo:breakdown:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['showInfo:breakdown:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="breakdownList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号" align="center" prop="id" />
+      <el-table-column label="战区" align="center" prop="warZone" />
+      <el-table-column label="单位" align="center" prop="organization" />
+      <el-table-column label="发现时机" align="center" prop="discoveryTiming" />
+      <el-table-column label="专业" align="center" prop="major" />
+      <el-table-column label="故障描述" align="center" prop="describe" />
+      <el-table-column label="故障原因" align="center" prop="reason" />
+      <el-table-column label="故障件名称" align="center" prop="unitName" />
+      <el-table-column label="故障件型别" align="center" prop="unitType" />
+      <el-table-column label="故障件所属系统" align="center" prop="unitSystem" />
+      <el-table-column label="故障后果" align="center" prop="consequence" />
+      <el-table-column label="故障责任" align="center" prop="duty" />
+      <el-table-column label="故障件名称" align="center" prop="name" />
+      <el-table-column label="故障件号码" align="center" prop="number" />
+      <el-table-column label="排除方法" align="center" prop="method" />
+      <el-table-column label="故障修复时间" align="center" prop="repairTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.repairTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="故障状态" align="center" prop="status" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['showInfo:breakdown:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['showInfo:breakdown:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改故障信息对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="战区" prop="warZone">
+          <el-input v-model="form.warZone" placeholder="请输入战区" />
+        </el-form-item>
+        <el-form-item label="单位" prop="organization">
+          <el-input v-model="form.organization" placeholder="请输入单位" />
+        </el-form-item>
+        <el-form-item label="发现时机" prop="discoveryTiming">
+          <el-input v-model="form.discoveryTiming" placeholder="请输入发现时机" />
+        </el-form-item>
+        <el-form-item label="专业" prop="major">
+          <el-input v-model="form.major" placeholder="请输入专业" />
+        </el-form-item>
+        <el-form-item label="故障描述" prop="describe">
+          <el-input v-model="form.describe" placeholder="请输入故障描述" />
+        </el-form-item>
+        <el-form-item label="故障原因" prop="reason">
+          <el-input v-model="form.reason" placeholder="请输入故障原因" />
+        </el-form-item>
+        <el-form-item label="故障件名称" prop="unitName">
+          <el-input v-model="form.unitName" placeholder="请输入故障件名称" />
+        </el-form-item>
+        <el-form-item label="故障件所属系统" prop="unitSystem">
+          <el-input v-model="form.unitSystem" placeholder="请输入故障件所属系统" />
+        </el-form-item>
+        <el-form-item label="故障后果" prop="consequence">
+          <el-input v-model="form.consequence" placeholder="请输入故障后果" />
+        </el-form-item>
+        <el-form-item label="故障责任" prop="duty">
+          <el-input v-model="form.duty" placeholder="请输入故障责任" />
+        </el-form-item>
+        <el-form-item label="故障件名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入故障件名称" />
+        </el-form-item>
+        <el-form-item label="故障件号码" prop="number">
+          <el-input v-model="form.number" placeholder="请输入故障件号码" />
+        </el-form-item>
+        <el-form-item label="排除方法" prop="method">
+          <el-input v-model="form.method" placeholder="请输入排除方法" />
+        </el-form-item>
+        <el-form-item label="故障修复时间" prop="repairTime">
+          <el-date-picker clearable
+            v-model="form.repairTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择故障修复时间">
+          </el-date-picker>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listBreakdown, getBreakdown, delBreakdown, addBreakdown, updateBreakdown } from "@/api/showInfo/breakdown";
+
+export default {
+  name: "Breakdown",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 故障信息表格数据
+      breakdownList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        warZone: null,
+        organization: null,
+        discoveryTiming: null,
+        major: null,
+        describe: null,
+        reason: null,
+        unitName: null,
+        unitType: null,
+        unitSystem: null,
+        consequence: null,
+        duty: null,
+        name: null,
+        number: null,
+        method: null,
+        repairTime: null,
+        status: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询故障信息列表 */
+    getList() {
+      this.loading = true;
+      listBreakdown(this.queryParams).then(response => {
+        this.breakdownList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        warZone: null,
+        organization: null,
+        discoveryTiming: null,
+        major: null,
+        describe: null,
+        reason: null,
+        unitName: null,
+        unitType: null,
+        unitSystem: null,
+        consequence: null,
+        duty: null,
+        name: null,
+        number: null,
+        method: null,
+        repairTime: null,
+        status: "0",
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加故障信息";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getBreakdown(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改故障信息";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateBreakdown(this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addBreakdown(this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除故障信息编号为"' + ids + '"的数据项?').then(function() {
+        return delBreakdown(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('showInfo/breakdown/export', {
+        ...this.queryParams
+      }, `breakdown_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>

+ 186 - 0
src/views/showInfo/breakdown/show/index.vue

@@ -0,0 +1,186 @@
+<template>
+  <div class="app-container">
+    <div ref="lineChart" style="width: 100%; height: 400px;"></div>
+    <div ref="pieChart" style="height: 400px;"></div>
+    <div ref="pieChart2" style="height: 400px;"></div>
+  </div>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+
+export default {
+  name: "BrakDownShow",
+  data() {
+    return {
+      lineChartData: [],
+      pieChartData: [],
+      pieChartData2: [],
+    };
+  },
+  mounted() {
+    this.initLineChartData(); // 初始化图表数据
+    this.initLineChart(); // 初始化图表
+    this.initPieChartData();
+    this.initPieChart()
+    this.initPieChartData2();
+    this.initPieChart2()
+  },
+  methods: {
+    /**
+     * 初始化图表数据
+     */
+    initLineChartData() {
+      // 模拟数据
+      this.lineChartData = [
+        { date: '2022-01', value: 100 },
+        { date: '2022-02', value: 200 },
+        { date: '2022-03', value: 150 },
+        { date: '2022-04', value: 300 },
+        { date: '2022-05', value: 250 },
+        { date: '2022-06', value: 280 },
+      ];
+    },
+    /**
+     * 初始化图表
+     */
+    initLineChart() {
+      // 基于准备好的dom,初始化echarts实例
+      const chartDom = this.$refs.lineChart;
+      const myChart = echarts.init(chartDom);
+      // const myChart = echarts.init(document.getElementById('lineChart'));
+
+      // 指定图表的配置项和数据
+      const option = {
+        title: {
+          text: '月度故障统计',
+          textStyle: {
+            color: 'white'
+          }
+        },
+        tooltip: {},
+        xAxis: {
+          type: 'category',
+          data: this.lineChartData.map((item) => item.date),
+          axisLabel: {
+            color: 'white'
+          }
+        },
+        yAxis: {
+          type: 'value',
+          axisLabel: {
+            color: 'white'
+          }
+        },
+        series: [{
+          data: this.lineChartData.map((item) => item.value),
+          type: 'line',
+          itemStyle: {
+            color: 'white'
+          },
+          lineStyle: {
+            color: 'white'
+          },
+          label: {
+            show: true,  // 是否显示节点信息
+            position: 'top',  // 节点信息显示在节点的位置
+            color: 'white',  // 节点信息的颜色
+            fontSize: '12',  // 节点信息的字体大小
+            formatter: function (params) {
+              return params.data  // 显示具体数值
+            }
+          }
+        }]
+      };
+      // 上述代码中,在title、xAxis、yAxis和series的属性中都添加了textStyle或color属性,并将其设置为白色。这样就可以改变文字颜色了。如果你需要修改其他部分的颜色,可以根据需要查找对应的属性设置。
+
+      // 使用刚指定的配置项和数据显示图表。
+      myChart.setOption(option);
+    },
+
+    initPieChartData() {
+      this.pieChartData =  [
+        {value: 15, name: '分类1', itemStyle: {color: '#00FFFF'}},
+        {value: 25, name: '分类2', itemStyle: {color: '#FF6347'}},
+        {value: 10, name: '分类3', itemStyle: {color: '#9ACD32'}},
+        {value: 20, name: '分类4', itemStyle: {color: '#FFA500'}},
+        {value: 30, name: '分类5', itemStyle: {color: '#7FFF00'}},
+      ]
+    },
+    initPieChart(){
+      const chartDom = this.$refs.pieChart;
+      const myChart = echarts.init(chartDom);
+
+      let pieChartOption =  {
+        title: {
+          text: '月度故障机型统计',
+          textStyle: {
+            color: 'white'
+          }
+        },
+        series: [{
+          name: '分类',
+          type: 'pie',
+          data: this.pieChartData,
+          label: {
+            color: 'white',
+            fontSize: 16,
+            formatter: function(params) {
+              const percent = params.percent.toFixed(0);
+              const quantity = params.value;
+              return params.name + ': ' + quantity + '个 (' + percent + '%)';
+            }
+          }
+        }]
+      }
+      myChart.setOption(pieChartOption);
+    },
+
+    initPieChartData2() {
+      this.pieChartData =  [
+        {value: 15, name: '分类1', itemStyle: {color: '#00FFFF'}},
+        {value: 25, name: '分类2', itemStyle: {color: '#FF6347'}},
+        {value: 10, name: '分类3', itemStyle: {color: '#9ACD32'}},
+        {value: 20, name: '分类4', itemStyle: {color: '#FFA500'}},
+        {value: 30, name: '分类5', itemStyle: {color: '#7FFF00'}},
+      ]
+    },
+    initPieChart2(){
+      const chartDom = this.$refs.pieChart2;
+      const myChart = echarts.init(chartDom);
+
+      let pieChartOption =  {
+        title: {
+          text: '月度故障机型统计',
+          textStyle: {
+            color: 'white'
+          }
+        },
+        series: [{
+          name: '分类',
+          type: 'pie',
+          data: this.pieChartData2,
+          label: {
+            color: 'white',
+            fontSize: 16,
+            formatter: function(params) {
+              const percent = params.percent.toFixed(0);
+              const quantity = params.value;
+              return params.name + ': ' + quantity + '个 (' + percent + '%)';
+            }
+          }
+        }]
+      }
+      myChart.setOption(pieChartOption);
+    },
+    
+    color16(){//十六进制颜色随机
+      const r = Math.floor(Math.random()*256);
+      const g = Math.floor(Math.random()*256);
+      const b = Math.floor(Math.random()*256);
+      const color = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`;
+      return color;
+    }
+  }
+}
+</script>

+ 223 - 0
src/views/showInfo/breakdown/statistics/index.vue

@@ -0,0 +1,223 @@
+<template>
+  <div class="app-container">
+    <el-row>
+      <div ref="lineChart" style="width: 100%; height: 400px;"></div>
+    </el-row>
+    <el-row>
+      <el-col :span="12">
+        <div ref="pieChart" style="height: 400px;"></div>
+      </el-col>
+      <el-col :span="12">
+        <div ref="pieChart2" style="height: 400px;"></div>
+      </el-col>
+    </el-row>
+    
+    
+  </div>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+
+export default {
+  name: "BrakDownShow",
+  data() {
+    return {
+      lineChartData: [],
+      pieChartData: [],
+      pieChartData2: [],
+    };
+  },
+  mounted() {
+    this.initLineChartData(); // 初始化图表数据
+    this.initLineChart(); // 初始化图表
+    this.initPieChartData();
+    this.initPieChart();
+    this.initPieChartData2();
+    this.initPieChart2();
+  },
+  methods: {
+    /**
+     * 初始化图表数据
+     */
+    initLineChartData() {
+      // 模拟数据
+      this.lineChartData = [
+        { date: '2022-01', value: 100 },
+        { date: '2022-02', value: 200 },
+        { date: '2022-03', value: 150 },
+        { date: '2022-04', value: 300 },
+        { date: '2022-05', value: 250 },
+        { date: '2022-06', value: 280 },
+      ];
+    },
+    /**
+     * 初始化图表
+     */
+    initLineChart() {
+      // 基于准备好的dom,初始化echarts实例
+      const chartDom = this.$refs.lineChart;
+      const myChart = echarts.init(chartDom);
+      // const myChart = echarts.init(document.getElementById('lineChart'));
+
+      // 指定图表的配置项和数据
+      const option = {
+        title: {
+          text: '月度故障统计',
+          textStyle: {
+            color: 'white'
+          }
+        },
+        tooltip: {},
+        xAxis: {
+          type: 'category',
+          data: this.lineChartData.map((item) => item.date),
+          axisLabel: {
+            color: 'white'
+          }
+        },
+        yAxis: {
+          type: 'value',
+          axisLabel: {
+            color: 'white'
+          }
+        },
+        series: [{
+          data: this.lineChartData.map((item) => item.value),
+          type: 'line',
+          itemStyle: {
+            color: 'white'
+          },
+          lineStyle: {
+            color: 'white'
+          },
+          label: {
+            show: true,  // 是否显示节点信息
+            position: 'top',  // 节点信息显示在节点的位置
+            color: 'white',  // 节点信息的颜色
+            fontSize: '12',  // 节点信息的字体大小
+            formatter: function (params) {
+              return params.data  // 显示具体数值
+            }
+          }
+        }]
+      };
+      // 上述代码中,在title、xAxis、yAxis和series的属性中都添加了textStyle或color属性,并将其设置为白色。这样就可以改变文字颜色了。如果你需要修改其他部分的颜色,可以根据需要查找对应的属性设置。
+
+      // 使用刚指定的配置项和数据显示图表。
+      myChart.setOption(option);
+    },
+
+    initPieChartData() {
+      this.pieChartData =  [
+        {value: 15, name: '歼20', itemStyle: {color: '#00FFFF'}},
+        {value: 25, name: '歼16', itemStyle: {color: '#FF6347'}},
+        {value: 10, name: '运20', itemStyle: {color: '#9ACD32'}},
+        {value: 20, name: '直15', itemStyle: {color: '#FFA500'}},
+        {value: 30, name: '轰6', itemStyle: {color: '#7FFF00'}},
+      ]
+    },
+    initPieChart(){
+      const chartDom = this.$refs.pieChart;
+      const myChart = echarts.init(chartDom);
+
+      let pieChartData = this.pieChartData;
+      // 大到小排序
+      pieChartData.sort(function(a, b) {
+        return b.value - a.value;
+      });
+
+      let pieChartOption =  {
+        title: { // 大标题
+          text: '月度故障机型统计',
+          textStyle: {
+            color: 'white'
+          }
+        },
+        series: [{ // 分类数据
+          name: '分类',
+          type: 'pie',
+          data: pieChartData,
+          label: { // 样式
+            color: 'white',
+            fontSize: 16,
+            formatter: function(params) {
+              const percent = params.percent.toFixed(0);
+              const quantity = params.value;
+              return params.name + ': ' + quantity + '个 (' + percent + '%)';
+            }
+          },
+          // emphasis: { // 在 emphasis 中,我们设置了 label.show 属性为 true,表示鼠标悬浮时显示分类名称
+          //   label: {
+          //     show: true,
+          //     formatter: function(params) {
+          //       return params.name;
+          //     }
+          //   }
+          // }
+        }]
+      }
+      myChart.setOption(pieChartOption);
+    },
+
+    initPieChartData2() {
+      this.pieChartData2 =  [
+        {value: 3, name: '空调', itemStyle: {color: '#00FFFF'}},
+        {value: 11, name: '增压', itemStyle: {color: '#FFA500'}},
+        {value: 39, name: '翼身', itemStyle: {color: '#7FFF00'}},
+        {value: 28, name: '飞行控制', itemStyle: {color: '#FF6347'}},
+        {value: 2, name: '起落架', itemStyle: {color: '#9ACD32'}},
+      ]
+    },
+    initPieChart2(){
+      const chartDom = this.$refs.pieChart2;
+      const myChart = echarts.init(chartDom);
+      let pieChartData = this.pieChartData2;
+      // 大到小排序
+      pieChartData.sort(function(a, b) {
+        return b.value - a.value;
+      });
+
+      let pieChartOption =  {
+        title: {
+          text: '月度故障专业统计',
+          textStyle: {
+            color: 'white'
+          }
+        },
+        series: [{
+          name: '分类',
+          type: 'pie',
+          data: pieChartData,
+          label: {
+            color: 'white',
+            fontSize: 16,
+            formatter: function(params) {
+              const percent = params.percent.toFixed(0);
+              const quantity = params.value;
+              return params.name + ': ' + quantity + '个 (' + percent + '%)';
+            }
+          },
+          // emphasis: { // 在 emphasis 中,我们设置了 label.show 属性为 true,表示鼠标悬浮时显示分类名称
+          //   label: {
+          //     show: true,
+          //     formatter: function(params) {
+          //       return params.name;
+          //     }
+          //   }
+          // }
+        }]
+      }
+      myChart.setOption(pieChartOption);
+    },
+    
+    color16(){//十六进制颜色随机
+      const r = Math.floor(Math.random()*256);
+      const g = Math.floor(Math.random()*256);
+      const b = Math.floor(Math.random()*256);
+      const color = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`;
+      return color;
+    }
+  }
+}
+</script>

部分文件因为文件数量过多而无法显示