Browse Source

Merge branch 'zhuhao' of http://1.116.113.26:8088/zhuliu/xiaoshi_system into zhuhao

zhuhao 2 năm trước cách đây
mục cha
commit
8f4c64603c

+ 18 - 8
package-lock.json

@@ -4664,6 +4664,11 @@
       "integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=",
       "dev": true
     },
+    "driver.js": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/driver.js/-/driver.js-1.3.0.tgz",
+      "integrity": "sha512-ilUkVc5iMIYfMd8FdWy8n5Wv//gsJuRP+lo8QfWpwP9c0UGOgD7P9nVQMZwcdW84aqAZHHUHrV7GgiopAN6HUQ=="
+    },
     "duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.nlark.com/duplexer/download/duplexer-0.1.2.tgz",
@@ -6694,6 +6699,11 @@
         "side-channel": "^1.0.4"
       }
     },
+    "intro.js": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmmirror.com/intro.js/-/intro.js-7.2.0.tgz",
+      "integrity": "sha512-qbMfaB70rOXVBceIWNYnYTpVTiZsvQh/MIkfdQbpA9di9VBfj1GigUPfcCv3aOfsbrtPcri8vTLTA4FcEDcHSQ=="
+    },
     "ip": {
       "version": "1.1.5",
       "resolved": "https://registry.nlark.com/ip/download/ip-1.1.5.tgz",
@@ -12385,7 +12395,7 @@
     },
     "vue-loader-v16": {
       "version": "npm:vue-loader@16.8.3",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
+      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
       "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
       "dev": true,
       "optional": true,
@@ -12397,7 +12407,7 @@
       "dependencies": {
         "ansi-styles": {
           "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
           "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
           "dev": true,
           "optional": true,
@@ -12407,7 +12417,7 @@
         },
         "chalk": {
           "version": "4.1.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
           "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
           "dev": true,
           "optional": true,
@@ -12418,7 +12428,7 @@
         },
         "color-convert": {
           "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
           "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
           "dev": true,
           "optional": true,
@@ -12428,21 +12438,21 @@
         },
         "color-name": {
           "version": "1.1.4",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true,
           "optional": true
         },
         "has-flag": {
           "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true,
           "optional": true
         },
         "loader-utils": {
           "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
           "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
           "dev": true,
           "optional": true,
@@ -12454,7 +12464,7 @@
         },
         "supports-color": {
           "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
           "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "optional": true,

+ 2 - 0
package.json

@@ -10,10 +10,12 @@
   "dependencies": {
     "@riophae/vue-treeselect": "^0.4.0",
     "core-js": "^3.6.5",
+    "driver.js": "^1.3.0",
     "echarts": "^5.2.2",
     "element-ui": "^2.15.7",
     "flowchart-vue": "^0.30.0",
     "html2canvas": "^1.3.3",
+    "intro.js": "^7.2.0",
     "js-cookie": "^3.0.1",
     "less": "^4.1.2",
     "less-loader": "^5.0.0",

+ 1 - 1
public/index.html

@@ -8,6 +8,6 @@
     <title><%= htmlWebpackPlugin.options.title %></title>
 </head>
 <body>
-<div id="app"></div>
+<div id="app" ></div>
 </body>
 </html>

+ 13 - 0
src/App.vue

@@ -37,6 +37,7 @@
 <script>
 import feedback from "@/views/feedback/components/feedback.vue";
 import pizhu from "@/views/workspace/gaoliang/components/pizhu.vue";
+import moment from 'moment'
 export default {
   name: 'app',
   components: {
@@ -60,12 +61,20 @@ export default {
   created() {
   },
   mounted() {
+    //判断是否在系统更新期间
     var time = new Date(this.$c.updateTime).getTime()
     var time2 = new Date().getTime()
     if(time2 < time && !localStorage.canShow){
         this.$router.push({path: '/'})
         return false
     }
+    //特殊日期设置主题
+    var today = moment().format('MM-DD')
+    var index = this.$c.specialDays.indexOf(today)
+    if(index!=-1){
+      document.body.style.filter = 'grayscale(100%)'
+    }
+    //关闭菜单
     document.addEventListener('mousedown',function(e){
       let btn = document.getElementsByClassName("caidan");
       let box = document.getElementsByClassName('pizhu')
@@ -173,6 +182,10 @@ export default {
 }
 </style>
 <style lang="scss">
+//driver.js
+.driver-fix-stacking .header {
+  position:relative;
+}
 
 .showPiZhu{
   position: absolute;

+ 1 - 0
src/config/index.js

@@ -1,6 +1,7 @@
 export default {
     baseURL: "/api",
     updateTime:'2023-08-04 08:00:00',
+    specialDays:['05-12','09-18','12-13'],
     host: window.location.host,
     staticURL: process.env.NODE_ENV === 'production' ? 'http://192.168.0.7:8081' : 'http://192.168.0.7:8081',
 }

+ 8 - 1
src/main.js

@@ -58,7 +58,14 @@ Vue.use(Charts)
 Vue.use(Particles)
 // Vue.use(Element)
 
- 
+// 首页引导插件
+import intro from 'intro.js' // introjs库
+import 'intro.js/introjs.css' // introjs默认css样式
+// introjs还提供了多种主题,可以通过以下方式引入
+import 'intro.js/themes/introjs-modern.css' // introjs主题
+// 把intro.js加入到vue的prototype中,方便使用,就可以直接通过this.$intro()来调用了
+Vue.prototype.$intro = intro 
+
 import i18n from '@/components/language'  
  
  Vue.use(Element,{

+ 1 - 0
src/store/getters.js

@@ -9,4 +9,5 @@ export default {
   width: state => state.user.width,
   webSocket: state => state.user.webSocket,
   prefix: state => state.user.prefix,
+  contextMenu:state => state.contextMenu,
 }

+ 3 - 1
src/store/index.js

@@ -9,6 +9,7 @@ import analyse from './modules/analyse'
 import admin from './modules/admin'
 import getters from './getters'
 import dictMessage from "./modules/dictMessage"
+import contextMenu from './modules/contextMenu'
 
 Vue.use(Vuex)
 
@@ -21,7 +22,8 @@ export default new Vuex.Store({
     analyse,
     admin,
     patent,
-    dictMessage
+    dictMessage,
+    contextMenu
   },
   getters
 })

+ 63 - 0
src/store/modules/contextMenu.js

@@ -0,0 +1,63 @@
+export default {
+  state: {
+    menuContent: [
+        {
+            name: "波浪线",
+            method: "wave",
+        },
+        {
+            name: "下划线",
+            method: "underscore",
+        },
+        {
+            name: "高亮",
+            method: "highlight",
+        },
+        {
+            name: "批注",
+            method: "mark",
+        }
+    ], // 右键菜单内容
+    mark:{
+        color:'#ff0000',
+        scratchType:2,
+        permissionType:1,
+        rangeType:true,
+        content:'',
+        remark:'',
+    },//选中文本信息
+    clientX: "", // left
+    clientY: "",
+    displayContextMenu: false, // 是否展示右键菜单
+  },
+  mutations: {
+    SET_CONTEXT_MENU: (state, payload) => {
+      state.displayContextMenu = payload.displayContextMenu;
+      state.clientX = payload.clientX;
+      state.clientY = payload.clientY;
+      if(payload.menuContent && payload.menuContent.length>0)
+      {
+        var a = [
+            {
+                name: "波浪线",
+                method: "wave",
+            },
+            {
+                name: "下划线",
+                method: "underscore",
+            },
+            {
+                name: "高亮",
+                method: "highlight",
+            },
+            {
+                name: "批注",
+                method: "mark",
+            }
+        ]
+       state.menuContent =a.concat(payload.menuContent) ; 
+      }
+      
+    },
+  },
+};

+ 160 - 0
src/utils/model/contextMenu/index.vue

@@ -0,0 +1,160 @@
+<template>
+  <div
+    ref="myContextMenu"
+    class="context-menu"
+    v-show="contextMenu.displayContextMenu"
+    :style="{
+      left: contextMenu.clientX + 'px',
+      top: contextMenu.clientY + 'px',
+    }"
+  >
+  <div class="contentMenu">
+    <!-- <div class="dropbtn" :style='{"background-color":mark.color,"border-radius":"50%","width":"12px","height":"12px","margin-top":"1px"}'>
+        <el-input type="color" v-model="mark.color"  style="opacity: 0;user-select:none;" @input="changeColor()"/>
+    </div> -->
+    <div class="color_item" :style='{"background-color":contextMenu.mark.color}'>
+        <el-input type="color" v-model="contextMenu.mark.color"  @input="changeColor()"/>
+        <!-- <el-color-picker popper-class="menu_color" v-model="contextMenu.mark.color" size="mini" @change="changeColor"></el-color-picker> -->
+    </div>
+    <div 
+        class="item"
+        v-for="(item, i) in contextMenu.menuContent" 
+        :key="i"
+        :class="item.disabled ? 'disabled' : ''"
+        @click="emitEvent(item.method)">
+        {{ item.name }}
+        </div>
+  </div>
+  </div>
+</template>
+    
+<script>
+import { mapGetters } from "vuex";
+export default {
+  name: "ContextMenu",
+  data() {
+    return {
+    };
+  },
+  computed: {
+    ...mapGetters(["contextMenu"]),
+    displayContextMenu(){
+        return this.$store.state.contextMenu.displayContextMenu
+    }
+  },
+  watch:{
+    displayContextMenu(val){
+        if(val){
+            this.$nextTick(()=>{
+                var maxWidth = document.body.clientWidth
+                var menuWidth = this.$refs.myContextMenu.clientWidth
+                console.log(maxWidth,menuWidth,this.contextMenu.clientX)
+                if(this.contextMenu.clientX + menuWidth > (maxWidth-10)){
+                    this.$refs.myContextMenu.style.width = menuWidth + 'px'
+                    this.contextMenu.clientX -= (this.contextMenu.clientX + menuWidth - maxWidth + 10)
+                }
+            }) 
+        }else{
+            this.$refs.myContextMenu.style.width = ''
+        }
+    }
+  },
+  mounted(){
+    this.$nextTick(()=>{
+        window.addEventListener('mousedown',()=>{
+            this.$store.commit("SET_CONTEXT_MENU", 
+                {
+                    displayContextMenu: false, 
+                }
+            )
+        })
+    })
+   
+  },
+  methods: {
+    emitEvent(type) {
+      this.$emit("operateDirectory", type);
+    },
+    changeColor(){
+        this.$emit("operateDirectory", 'changeColor');
+    },
+  },
+};
+</script>
+  
+<style lang="scss">
+    .menu_color{
+        .el-button--text{
+            display: none;
+        }
+    }
+    .context-menu{
+        .el-color-picker__trigger{
+            height: 22px;
+            width: 22px;
+            border:none;
+            .el-color-picker__color{
+                border-radius: 50%;
+                border:none;
+            }
+        }
+    }
+</style>
+<style lang="scss" scoped>
+.context-menu {
+    height: 30px;
+  user-select:none;
+  position: absolute;
+  left: 0;
+  bottom: 0;
+  top: 0;
+  background: #fff;
+  color: #34495e;
+  min-width: 100px;
+  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
+  border-radius: 15px;
+  cursor: pointer;
+  z-index: 1002;
+  .color_item{
+    border-radius:50%;
+    width:12px;
+    height:12px;
+    margin-top:1px;
+    cursor: pointer;
+  }
+  .color_item>*{
+    cursor: pointer;
+    opacity: 0;
+    user-select: none;
+  }
+  .contentMenu {
+    text-align: center;
+    padding: 5px 10px;
+    display: flex;
+    align-items: center;
+    .item {
+      min-width: 54px !important;
+      white-space: nowrap;
+      padding: 3px 8px;
+      font-size: 12px;
+      list-style: none;
+      display: inline-block;
+      text-align-last: justify;
+      justify-content: space-between;
+      border-right:1px solid #E4E7ED;
+      cursor: pointer;
+      &:hover {
+        background: #edf6ff;
+      }
+    }
+    .item:last-child{
+        border-right:none;
+    }
+    .disabled {
+      color: #888585;
+      pointer-events: none;
+    }
+  }
+}
+
+</style>

+ 5 - 0
src/utils/model/index.js

@@ -10,6 +10,9 @@ import mySelectButton from './selectButton/index.vue';
 import myFormSearch from './search/searchIndex.vue';
 import myTimeChoose from './time/timeIndex.vue';
 
+import myContextMenu from './contextMenu/index.vue';
+
+
 var models = {
   myCustomSvg,
   myTree,
@@ -21,6 +24,8 @@ var models = {
   mySelectButton,
   myFormSearch,
   myTimeChoose,
+
+  myContextMenu
 }
 export default {
   install(Vue) {

+ 47 - 0
src/utils/model/route.vue

@@ -0,0 +1,47 @@
+<template>
+  <div style="width:100%;height:100%">
+    <myContextMenu></myContextMenu>
+    <div @mouseup="mouseup" style="width:100%;height:100%">
+
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {},
+  data() {
+    return {
+        show:false
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {
+    mouseup(e){
+        console.log(this.show)
+        e.preventDefault();
+        this.show = !this.show
+        this.$store.commit("SET_CONTEXT_MENU", 
+        {
+            clientX: e.clientX, // left
+            clientY: e.clientY,
+            displayContextMenu: this.show, 
+        }
+        )
+        // document.onclick=()=>{
+        //     this.$store.commit("SET_CONTEXT_MENU", 
+        //         {
+        //             displayContextMenu: false, 
+        //         }
+        //     )
+        // }
+    }
+  },
+};
+</script>
+<style lang="scss" scoped>
+</style>

+ 2 - 2
src/views/EnterprisePatentDatabase/index.vue

@@ -2,7 +2,7 @@
   <div>
     <el-container>
         <el-header>
-            <div>
+            <div id="step1">
               <mySearch style="width:500px" :SearchFields="searchFiled" @search="search" :searchValue="searchOption" :disabled="!$permission('/workspace/project/check')"></mySearch>  
             </div>
             <div style="display:flex;margin-right:10px">
@@ -17,7 +17,7 @@
                   <el-button :type="queryShowType === '0' ? 'primary' : ''" @click="onChange2('0')" size="small">列表</el-button>
                   <el-button :type="queryShowType === '1' ? 'primary' : ''" @click="onChange2('1')" size="small">卡片</el-button>
                 </el-button-group>
-                <el-dropdown trigger="click" split-button type="primary" size="small">
+                <el-dropdown trigger="click" split-button type="primary" size="small" id="step2">
                     <p @click="handleAdd" v-disabled="!$permission('/workspace/project/add')">新增其他企业专利数据库</p>
                     <el-dropdown-menu slot="dropdown" class="text-align_center">
                         <!-- <el-dropdown-item @click.native="handleExport">导出列表</el-dropdown-item> -->

+ 15 - 9
src/views/home/index.vue

@@ -1,19 +1,22 @@
 <template>
   <div style="height:100%;width:80%;margin:0 auto;">
     <div>
-      <div>
+      <div id="step1">
         <carousel></carousel>
       </div>
         <div class="imgDiv">
           <img class="logo" src="@/assets/logo-3.png" alt="">
         </div>
-      <div class="home_search">
-        <el-input :placeholder="getPlaceholder()" v-model="queryParams.content" class="input-with-select">
-          <el-select v-model="queryParams.select" slot="prepend" placeholder="请选择" style="width:100px">
-            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
-          </el-select>
-          <el-button slot="append" icon="el-icon-search" @click="search"></el-button>
-        </el-input>
+      <div class="home_search" >
+        <div class="input_search" id="step2">
+          <el-input :placeholder="getPlaceholder()" v-model="queryParams.content" class="input-with-select">
+            <el-select v-model="queryParams.select" slot="prepend" placeholder="请选择" style="width:100px">
+              <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
+            </el-select>
+            <el-button slot="append" icon="el-icon-search" @click="search"></el-button>
+          </el-input>
+        </div>
+        
       </div>
     </div>
     <div :style="{'margin-top':margin_top}">
@@ -163,7 +166,7 @@ export default {
   .fixHeader{
     .input-with-select{
       // min-width: 654px;
-      width: 50%;
+      // width: 50%;
       // margin-left:20px;
     }
   }
@@ -195,6 +198,9 @@ export default {
   //   height: 40px;
   //   margin-right:20px;
   // }
+  .input_search{
+    width: 50%;
+  }
 }
 .home_search{
   

+ 57 - 0
src/views/layout/components/contextMenu.vue

@@ -0,0 +1,57 @@
+<template>
+  <div>
+    <myContextMenu @operateDirectory="getMethod"></myContextMenu>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {},
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {
+    getMethod(type){
+        if(this[type]){
+           this[type]() 
+        }
+    },
+    //波浪线
+    wave(){
+        
+    },
+    //下划线
+    underscore(){
+
+    },
+    //高亮
+    highlight(){
+
+    },
+    //批注
+    mark(){
+
+    },
+    //修改颜色
+    changeColor(){
+
+    },
+    //对比
+    contrast(){
+
+    },
+    //删除批注
+    deleteMark(){
+
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+</style>

+ 161 - 0
src/views/layout/components/guide.js

@@ -0,0 +1,161 @@
+/**
+ * intro.js新手指引工具
+ * introOption.steps = steps[title]
+ * this.$intro().setOptions(introOption).start()
+ */
+// const introOption= { // 参数对象
+//     prevLabel: '上一步',
+//     nextLabel: '下一步',
+//     skipLabel: '跳过',
+//     doneLabel: '完成',
+//     tooltipClass: 'intro-tooltip', /* 引导说明文本框的样式 */
+//     // highlightClass: 'intro-highlight', /* 说明高亮区域的样式 */
+//     exitOnEsc: true, /* 是否使用键盘Esc退出 */
+//     exitOnOverlayClick: false, /* 是否允许点击空白处退出 */
+//     keyboardNavigation: true, /* 是否允许键盘来操作 */
+//     showBullets: true, /* 是否使用点显示进度 */
+//     showProgress: false, /* 是否显示进度条 */
+//     showStepNumbers: false,//是否显示说明的数据步骤
+//     scrollToElement: true, /* 是否滑动到高亮的区域 */
+//     overlayOpacity: 0.75, // 遮罩层的透明度 0-1之间
+//     positionPrecedence: ['bottom', 'top', 'right', 'left'], /* 当位置选择自动的时候,位置排列的优先级 */
+//     disableInteraction: false, /* 是否禁止与元素的相互关联 */
+//     hidePrev: true, /* 是否在第一步隐藏上一步 */
+//     hideNext: true, /* 是否在最后一步隐藏下一步 */
+//     steps: [], /* steps步骤,可以写个工具类保存起来 */
+//     helperElementPadding: 2,//提示边框的 padding
+//     disableInteraction: false,//是否禁止与元素的相互关联
+//   }
+// const steps = {
+//     '首页':[
+//         { title: '系统使用指导', element: '#step1', intro: `鼠标悬浮在各个功能模块上,可快速查找系统对应操作SOP以及运维人员。`},
+//         { title: '个人信息', element: '#step2', intro: `点击个人头像/下拉图标,选择个人信息,初始密码为******,建议修改为个人账号密码。`, },
+//         { title: '重新引导', element: '#step3', intro: '点击此处可重新查看引导流程。', },
+//     ],
+// }
+
+const steps = {
+    '首页':[
+        {
+            element: "#step1", // 需要引导展示的iD
+            popover: {
+                title: "系统使用指导", //展示模块标题
+                description: "鼠标悬浮在各个功能模块上,可快速查找系统对应操作SOP以及运维人员。", // 展示模块类容
+                position: "right" // 模块的位置 可以定位 看自己了
+            } 
+        },
+        {
+            element: "#step2", // 需要引导展示的iD
+            popover: {
+                title: "个人信息", //展示模块标题
+                description: "点击个人头像/下拉图标,选择个人信息,初始密码为******,建议修改为个人账号密码。", // 展示模块类容
+                position: "right" // 模块的位置 可以定位 看自己了
+            } 
+        },
+        {
+            element: "#step3", // 需要引导展示的iD
+            popover: {
+                title: "重新引导", //展示模块标题
+                description: "点击此处可重新查看引导流程。", // 展示模块类容
+                position: "right" // 模块的位置 可以定位 看自己了
+            } 
+        },
+    ],
+    '企业专利数据库':[
+        {
+            element: "#step1", // 需要引导展示的iD
+            popover: {
+                title: "搜索", //展示模块标题
+                description: "可以搜索想要搜索的信息", // 展示模块类容
+                position: "right" // 模块的位置 可以定位 看自己了
+            } 
+        },
+        {
+            element: "#step2", // 需要引导展示的iD
+            sign:'/workspace/folder/merge/applicationMerge/delete',
+            popover: {
+                title: "新增", //展示模块标题
+                description: "可以新增企业专利数据库", // 展示模块类容
+                position: "right" // 模块的位置 可以定位 看自己了
+            } 
+        },
+        {
+            element: "#step3", // 需要引导展示的iD
+            sign:'s',
+            popover: {
+                title: "新增", //展示模块标题
+                description: "可以新增企业专利数据库", // 展示模块类容
+                position: "right" // 模块的位置 可以定位 看自己了
+            } 
+        },
+    ]
+}
+/**
+ * driver.js v1.3.0 新手指引工具
+ */
+import {driver} from 'driver.js'
+import 'driver.js/dist/driver.css'
+//配置
+const config ={
+    overlayOpacity: 0.75,
+    popoverClass: "scoped-class",
+    stagePadding: 10,
+    // showButtons: [ 'next','prev', 'close'], //1 pass an array of buttons to show
+    allowKeyboardControl:true,
+    allowClose: true, // 禁止点击外部关闭
+    showProgress:true,
+    progressText:'{{current}}/{{total}}',
+    doneBtnText: '完成', // 结束按钮的文字
+    animate: true, // 动画
+    stageBackground: '#ffffff', // 突出显示元素的背景颜色
+    nextBtnText: '下一步', // 下一步按钮的文字
+    prevBtnText: '上一步', // 上一步按钮的文字
+    closeBtnText: '关闭', // 关闭按钮的文字
+    // overlayColor:'#f40',
+        
+}
+    
+export const guide = {
+    methods: {
+         //打开新手指引
+         openGuide(title){
+            var firstRoute = localStorage.firstRoute
+            if(firstRoute){
+                var arr = JSON.parse(firstRoute)
+                var index = arr.indexOf(title)
+                if(index != -1){
+                    return false
+                }
+            }else{
+                var arr = []
+            }
+            this.startGuide(title,arr)
+            
+        },
+        //开始新手指引
+        startGuide(title,arr){
+            this.$nextTick(()=>{
+                var step = steps[title].filter(item=>{
+                    return !item.sign || this.$permission(item.sign)
+                })
+                const drivers =  driver({
+                    ...config,
+                    steps:step,
+                    // onCloseClick:() => {
+                    //     arr.push(title)
+                    //     localStorage.firstRoute = JSON.stringify(arr)
+                    //     drivers.destroy();
+                    // },
+                    onDestroyed:()=>{
+                        if(arr){
+                          arr.push(title)
+                          localStorage.firstRoute = JSON.stringify(arr)  
+                        }
+                        drivers.destroy();
+                    }
+                })
+                drivers.drive()
+            })
+        }
+    }
+  }

+ 113 - 4
src/views/layout/index.vue

@@ -16,15 +16,16 @@
           </div>
         </div>
       </el-header>
-      <el-main style="padding:0;padding-top:0px;overflow:auto;background:white">
+      <el-main style="padding:0;padding-top:0px;overflow:auto;background:white" >
         <!-- <el-header style="height:30px;color:brown;">
             <marquee behavior="scroll" direction="left" scrollamount="5" scrolldelay="100" hspace="10" vspace="10" align="middle" face="" color="white" size="">{{ text }}</marquee>
           </el-header> -->
-        <section class="wrapper">
+        <section class="wrapper" >
           <!-- <keep-alive>
             <router-view id="view" v-if="$route.meta.keepAlive"></router-view>
           </keep-alive> -->
           <router-view id="view" v-if="!$route.meta.keepAlive"></router-view>
+          <contextMenu></contextMenu>
         </section>
       </el-main>
     </el-container>
@@ -35,11 +36,14 @@
 import { mapGetters } from "vuex";
 import UserBar from "./components/UserBar";
 import { webSocket } from "./mixins";
+import { guide } from "./components/guide";
+import contextMenu from "./components/contextMenu.vue";
 export default {
   components: {
     UserBar,
+    contextMenu
   },
-  mixins: [webSocket],
+  mixins: [webSocket,guide],
   data() {
     return {
       showProjectName:false,
@@ -56,6 +60,7 @@ export default {
     $route() {
       this.button = this.$route.meta.button || []
       this.showProjectName = this.$route.meta.showProjectName
+      this.openGuide(this.$route.meta.title)
     },
     showProjectName(val){
       this.projectName = this.$s.getSession('projectName')
@@ -72,7 +77,7 @@ export default {
     this.getUserInfo()
     this.getRouter()
     this.DictMessage()
-    this.getPermissions() 
+    await this.getPermissions() 
     if (this.id) {
       this.$store.commit('SET_PROJECT_ID', parseInt(this.id))
     }
@@ -81,8 +86,10 @@ export default {
       await this.$store.dispatch('getCustomField', this.projectId)
       await this.$store.dispatch('getSystemField', this.projectId)
     }
+    this.openGuide(this.$route.meta.title)
   },
   methods: {
+    
     //获取专题库权限
     async getPermissions() {
       const response = await this.$api.getPermissions()
@@ -194,3 +201,105 @@ export default {
   }
 }
 </style>
+<style lang="scss">
+.introjs-helperLayer{
+    box-shadow: rgba(33, 33, 33, 0.8) 0px 0px 1px 0px, rgba(33, 33, 33, 0.5) 0px 0px 0px 5000px!important;
+    border: 3px dashed #409eff;
+}
+.new-tips{
+    color: #409eff;
+    line-height: 80px;
+    cursor: pointer;
+}
+.introjs-tooltip-title{
+    font-size: 16px;
+    width: 80%;
+    padding-top: 10px;
+}
+.warper {
+  width: 200px;
+  height: 100px;
+  line-height: 100px;
+  text-align: center;
+  border: 1px solid saddlebrown;
+}
+/* 重置引导组件样式(类似element-ui个人使用) */
+.intro-tooltip {
+  color: #ffff;
+  background: #2c3e50;
+}
+/* 引导提示框的位置 */
+.introjs-bottom-left-aligned {
+  left: 45% !important;
+}
+.introjs-right,
+.introjs-left {
+  top: 30%;
+}
+.intro-highlight {
+  background: rgba(255,255,255,0.5);
+}
+.introjs-arrow.left {
+  border-right-color: #2c3e50;
+}
+.introjs-arrow.top {
+  border-bottom-color: #2c3e50;
+}
+.introjs-arrow.right {
+  border-left-color: #2c3e50;
+}
+.introjs-arrow.bottom {
+  border-top-color: #2c3e50;
+}
+/* 提示框头部区域 */
+.introjs-tooltip-header {
+  padding-right: 0 !important;
+  padding-top: 0 !important;
+}
+.introjs-skipbutton {
+  color: #409eff !important;
+  font-size: 14px !important;
+  font-weight: normal !important;
+//   padding: 8px 10px !important ;
+}
+.introjs-tooltipbuttons {
+  border: none !important;
+}
+.introjs-tooltiptext {
+  font-size: 14px !important;
+  padding: 15px !important;
+}
+/* 提示框按钮 */
+.introjs-tooltipbuttons {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.introjs-button {
+  width: 50px !important;
+  text-align: center;
+  padding: 4px !important;
+  font-size: 12px !important;
+  font-weight: 500 !important;
+  border-radius: 3px !important;
+  border: none !important;
+}
+.introjs-button:last-child {
+  margin-left: 10px;
+}
+.introjs-prevbutton {
+  color: #606266 !important;
+  background: #fff !important;
+  border: 1px solid #dcdfe6 !important;
+}
+.introjs-nextbutton {
+  color: #fff !important;
+  background-color: #409eff !important;
+  border-color: #409eff !important;
+}
+.introjs-disabled {
+  color: #9e9e9e !important;
+  border-color: #bdbdbd !important;
+  background-color: #f4f4f4 !important;
+}
+</style>

+ 1 - 1
src/views/questionEvent/components/table.vue

@@ -70,7 +70,7 @@
         </template>
       </el-table-column>
     </el-table>
-    <div style="display:flex;flex-direction: row-reverse;margin:25px 0" v-if="show">
+    <div style="display:flex;flex-direction: row-reverse;margin:25px 0" v-if="show" id="step3">
         <el-link type="primary" style="font-size:16px" @click="checkMore">查看更多>>> </el-link>
     </div>
   </div>

+ 19 - 1
src/views/workspace/folder/articles/components/mixins.js

@@ -249,6 +249,11 @@ export const addContrast = {
         }
         else {
           this.currentSelectObj = {};
+          this.$store.commit("SET_CONTEXT_MENU", 
+            {
+                displayContextMenu: false, 
+            }
+          )
         }
         if (this.currentSelectObj.Id) {
           var a = JSON.parse(this.index)
@@ -273,9 +278,22 @@ export const addContrast = {
           a.rightPosition = this.currentSelectObj.rightPosition
           this.$store.commit("SET_PATENT_INDEX", a)
           this.showPizhu()
-        }
+          // this.$store.commit("SET_CONTEXT_MENU", 
+          //   {
+          //       clientX: e.clientX, // left
+          //       clientY: e.clientY,
+          //       displayContextMenu: true, 
+          //       menuContent:[
+          //         {
+          //           name:'对比',
+          //           methods:'contrast'
+          //         }
+          //       ]
+          //   })
+          }
       }
     },
+  
     // 打开批注框
     pizhu() {
       if (this.contrast.id == undefined) {