소스 검색

Merge branch 'http_test' of git.xiaojukeji.com:pu_qa_tool/thoth-frontend into http_test

qinzhipeng_v@didiglobal.com 4 년 전
부모
커밋
c286593790

+ 9 - 0
.prettierrc

@@ -0,0 +1,9 @@
+{
+  "eslintIntegration": true,
+  "stylelintIntegration": true,
+  "tabWidth": 2,
+  "singleQuote": true,
+  "semi": false,
+  "trailingComma": "none",
+  "arrowParens": "always"
+}

+ 47 - 30
src/App.vue

@@ -8,9 +8,9 @@
 import { mapGetters } from 'vuex'
 import { getGlobalInterface } from '@/api/data.js'
 import { getUserInfo } from '@/api/user.js'
+import { envTag } from '@/apiConfig/requestIP'
 // omega埋点工具包
 import OmegaTracker from '@didi/omega-tracker/lib/index.esm'
-const config = { appKey: 'omega6b172861f4' }
 
 export default {
   name: 'App',
@@ -19,16 +19,15 @@ export default {
   },
   mounted() {
     window.addEventListener('offline', () => {
-      this.$store.dispatch('global/setNoNetwork', true)// 处于断网状态
+      this.$store.dispatch('global/setNoNetwork', true) // 处于断网状态
     })
     window.addEventListener('online', () => {
-      this.$store.dispatch('global/setNoNetwork', false)// 网络恢复
+      this.$store.dispatch('global/setNoNetwork', false) // 网络恢复
+    })
+    getUserInfo().then((res) => {
+      localStorage.setItem('realname', res.data.chineseName)
+      localStorage.setItem('username', res.data.username)
     })
-    getUserInfo()
-      .then(res => {
-        localStorage.setItem('realname', res.data.chineseName)
-        localStorage.setItem('username', res.data.username)
-      })
   },
   created() {
     this.initRoutes()
@@ -47,17 +46,23 @@ export default {
     // },
     initOmegaTracker() {
       try {
-        const tracker = OmegaTracker.getTracker(config)
-        const _this = this
-        window.log = function({ c: master_func, d: detail_func }) {
-          const userName = localStorage.getItem('username')
-          const { bizId = null } = _this.$store.state.global || {}
-          tracker.trackEvent('phpublic_zhihui_project_management_ck', {
-            'biz_id': bizId,
-            'user': userName,
-            master_func,
-            detail_func
-          })
+        window.log = function ({ c: master_func, d: detail_func }) {
+          const { log } = console
+          log({ master_func, detail_func }, '埋点成功!')
+        }
+        if (envTag === 'online') {
+          const tracker = OmegaTracker.getTracker({ appKey: 'omega6b172861f4' })
+          const _this = this
+          window.log = function ({ c: master_func, d: detail_func }) {
+            const userName = localStorage.getItem('username')
+            const { bizId = null } = _this.$store.state.global || {}
+            tracker.trackEvent('phpublic_zhihui_project_management_ck', {
+              biz_id: bizId,
+              user: userName,
+              master_func,
+              detail_func
+            })
+          }
         }
       } catch (error) {
         console.error(error)
@@ -66,7 +71,7 @@ export default {
     initRoutes() {
       this.$store.dispatch('data/setRoutes', this.$router.options.routes)
       // 数据中心动态路由获取
-      getGlobalInterface().then(res => {
+      getGlobalInterface().then((res) => {
         this.$store.dispatch('data/setMenu', res.data)
         const dataCenterRoutes = []
         const route = {
@@ -95,8 +100,18 @@ export default {
           }
           for (const j in res.data[i].subMenus) {
             const routeChildrenItem = {
-              path: res.data[i].subMenus[j].path.replace('/', '') + '/' + i + '/' + j,
-              name: res.data[i].subMenus[j].subMenuName.replace('/', '') + '/' + i + '/' + j,
+              path:
+                res.data[i].subMenus[j].path.replace('/', '') +
+                '/' +
+                i +
+                '/' +
+                j,
+              name:
+                res.data[i].subMenus[j].subMenuName.replace('/', '') +
+                '/' +
+                i +
+                '/' +
+                j,
               component: () => import('@/views/data/index.vue'),
               meta: { title: res.data[i].subMenus[j].subMenuName }
             }
@@ -120,18 +135,20 @@ export default {
 
 <style>
 /* el-table头部 */
-.tableHead{
+.tableHead {
   color: rgba(0, 0, 0, 0.726);
 }
+
 /* 分页 */
-.el-pagination{
+.el-pagination {
   margin: 2% 0 2% 0;
 }
-.stylus-content{
-    width: 98%;
-    padding: 0.3% 1% 1% 1%;
-    margin: 0 auto;
-    background-color: #fff;
-    border-radius: 4px;
+
+.stylus-content {
+  width: 98%;
+  padding: 0.3% 1% 1% 1%;
+  margin: 0 auto;
+  background-color: #fff;
+  border-radius: 4px;
 }
 </style>

+ 80 - 0
src/assets/css/index.less

@@ -0,0 +1,80 @@
+:root {
+  --white-1: #fff;
+  --brand-1: #409eff;
+  --brand-2: #eef5fe;
+  --brand-3: #6AB4FF;
+  --font-1: #333;
+  --font-2: #444;
+  --font-3: #666;
+  --gray-1: #F7F8FC;
+  --gray-2: #e8e8e8;
+  --gray-3: #D1D0D0;
+  --gray-4: #fafafa;
+  --gray-5: #C1C4CB;
+  --gray-6: #F5F7FA;
+  --gray-7: #EAEAEA;
+  --gray-8: #999;
+  --grey-9: #E3E3E3;
+  --red-1: #F56C6C;
+  --red-2: #F5222D;
+  --yellow-1: #FF8952;
+  --yellow-2: #FA541C;
+  --yellow-3: #FAAD14;
+  --green-1: #7ED321;
+  --blue-1: #ebf5ff;
+  --blue-2: #409EFF;
+  --pink-1: #D675F0;
+}
+
+.yellowGradientColorText {
+  background: linear-gradient(45deg, #FCD56E, #F87046);
+  -webkit-background-clip: text;
+}
+.blueGradientColorText {
+  background: linear-gradient(45deg,#1FF6FF, #1C84FD);
+  -webkit-background-clip: text;
+}
+.greenGradientColorText {
+  background: linear-gradient(45deg, #A3FC2A, #0EB400);
+  -webkit-background-clip: text;
+}
+.violetGradientColorText {
+  background: linear-gradient(45deg, #D0ADFF, #A15DFF);
+  -webkit-background-clip: text;
+}
+
+.red {
+  color: var(--red-2);
+}
+.green {
+  color: var(--green-1);
+}
+.yellow {
+  color: var(--yellow-1);
+}
+.gray {
+  color: var(--font-3);
+}
+.blue {
+  color: var(--brand-1);
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  color: transparent;
+  -webkit-font-smoothing: antialiased;
+  -webkit-text-stroke-width: 0.2px;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+@font-face {
+  font-family: 'iconfont';  /* project id 2402558 */
+  src: url('//at.alicdn.com/t/font_2402558_ylag5taaxi.eot');
+  src: url('//at.alicdn.com/t/font_2402558_ylag5taaxi.eot?#iefix') format('embedded-opentype'),
+  url('//at.alicdn.com/t/font_2402558_ylag5taaxi.woff2') format('woff2'),
+  url('//at.alicdn.com/t/font_2402558_ylag5taaxi.woff') format('woff'),
+  url('//at.alicdn.com/t/font_2402558_ylag5taaxi.ttf') format('truetype'),
+  url('//at.alicdn.com/t/font_2402558_ylag5taaxi.svg#iconfont') format('svg');
+}

+ 1 - 0
src/components/newLayout/Aside.vue

@@ -108,6 +108,7 @@ export default {
     },
     // 路由跳转
     handleClickRouter(router) {
+      if (router.key) window.log({ c: 'entry', d: router.key })
       this.$router.push({ name: router.name })
     },
     // 展开/收起侧边栏

+ 185 - 55
src/components/newLayout/Head.vue

@@ -3,34 +3,69 @@
     <div class="head-logo">
       <svg-icon icon-class="zhihui-logo" @click="topHome()" />
     </div>
-    <div v-for="item in headList" :key="item.path" class="nav-tag" :class="{'active-nav-tag':activeNavTag === item.name}" @click="changeNavTag(item)">
+    <div
+      v-for="item in headList"
+      :key="item.path"
+      class="nav-tag"
+      :class="{ 'active-nav-tag': activeNavTag === item.name }"
+      @click="changeNavTag(item)"
+    >
       <div v-if="item.icon" class="icon">
-        <div v-show="notice && item.name.search(/个人工作台/)>=0" class="if-notice" />
+        <div
+          v-show="notice && item.name.search(/个人工作台/) >= 0"
+          class="if-notice"
+        />
         <svg-icon :icon-class="item.icon" />
       </div>
       <div class="name">{{ item.name }}</div>
     </div>
-    <div @mouseleave="target = true">
+<!--    <div @mouseleave="target = true">
       <div :class="[target ? 'nav-div1' : 'nav-div2']">
-        <el-tooltip v-if="!target" class="item" effect="dark" content="工具集合" placement="right">
-          <div class="div-child" @click="goto('Interface')"><svg-icon icon-class="b_工具集合" /></div>
+        <el-tooltip
+          v-if="!target"
+          class="item"
+          effect="dark"
+          content="工具集合"
+          placement="right"
+        >
+          <div class="div-child" @click="goto('Interface')">
+            <svg-icon icon-class="b_工具集合" />
+          </div>
         </el-tooltip>
-        <el-tooltip v-if="!target" class="item" effect="dark" content="环境平台" placement="right">
-          <div class="div-child" @click="goto('env')"><svg-icon icon-class="b_环境平台" /></div>
+        <el-tooltip
+          v-if="!target"
+          class="item"
+          effect="dark"
+          content="环境平台"
+          placement="right"
+        >
+          <div class="div-child" @click="goto('env')">
+            <svg-icon icon-class="b_环境平台" />
+          </div>
         </el-tooltip>
       </div>
       <div class="nav-div3 nav-circular" />
       <div class="nav-div4 nav-circular" @mouseenter="target = false" />
-    </div>
+    </div>-->
     <!-- <div v-show="navTagType === 2" class="nav-tag-type" @click="setNavTagType(1)">
       <i class="el-icon-notebook-2" style="transform: rotate(90deg);" />
     </div>
     <div v-show="navTagType === 1" class="nav-tag-type" @click="setNavTagType(2)">
       <i class="el-icon-notebook-2" />
     </div> -->
-    <el-tooltip class="item" effect="dark" content="用户指导手册" placement="right">
-      <el-link class="user-tip" href="https://base3.xiaojukeji.com/docs/zhihui/" target="_blank">
-        <svg-icon style="width: 24px; height: 24px;" icon-class="question" />
+    <HeaderMenu />
+    <el-tooltip
+      class="item"
+      effect="dark"
+      content="用户指导手册"
+      placement="right"
+    >
+      <el-link
+        class="user-tip"
+        href="https://base3.xiaojukeji.com/docs/zhihui/"
+        target="_blank"
+      >
+        <svg-icon style="width: 24px; height: 24px" icon-class="question" />
       </el-link>
     </el-tooltip>
     <div v-if="userInfo" class="user-info">
@@ -47,11 +82,15 @@
                   :value="navTagType === 1"
                   :size="size"
                   class="mr10"
-                  @change="setNavTagType(navTagType === 2 ? 1: 2)"
+                  @change="setNavTagType(navTagType === 2 ? 1 : 2)"
                 />
                 <span class="label-text">左侧导航</span>
-                <el-tooltip effect="dark" content="可设置为“左侧导航”或“顶部导航”" placement="top-start">
-                  <i class="el-icon-info" style="vertical-align: text-bottom;" />
+                <el-tooltip
+                  effect="dark"
+                  content="可设置为“左侧导航”或“顶部导航”"
+                  placement="top-start"
+                >
+                  <i class="el-icon-info" style="vertical-align: text-bottom" />
                 </el-tooltip>
               </div>
               <div class="label line">
@@ -59,11 +98,19 @@
                   :value="openPageHandle === 'blank'"
                   :size="size"
                   class="mr10"
-                  @change="setOpenPageHandle(openPageHandle === 'blank' ? 'self' : 'blank')"
+                  @change="
+                    setOpenPageHandle(
+                      openPageHandle === 'blank' ? 'self' : 'blank'
+                    )
+                  "
                 />
                 <span class="label-text">详情页新标签页打开</span>
-                <el-tooltip effect="dark" content="可设置详情页在“新标签页打开“,或”当前标签页“打开。" placement="top-start">
-                  <i class="el-icon-info" style="vertical-align: text-bottom;" />
+                <el-tooltip
+                  effect="dark"
+                  content="可设置详情页在“新标签页打开“,或”当前标签页“打开。"
+                  placement="top-start"
+                >
+                  <i class="el-icon-info" style="vertical-align: text-bottom" />
                 </el-tooltip>
               </div>
             </div>
@@ -79,14 +126,17 @@
               </div>
               <div class="label">
                 <span class="outLogin" @click="layout()">
-                  <i class="el-icon-switch-button icon" style="margin-right:4px" />
+                  <i
+                    class="el-icon-switch-button icon"
+                    style="margin-right: 4px"
+                  />
                   <span class="label">退出</span>
                 </span>
               </div>
             </div>
           </div>
         </template>
-        <img :src="userInfo.phoneUrl">
+        <img :src="userInfo.phoneUrl" />
       </a-popover>
     </div>
   </div>
@@ -94,16 +144,18 @@
 <script>
 import { mapGetters } from 'vuex'
 import routes from '@/router/newRouter'
+import HeaderMenu from './components/menu'
 import websocket from '@/views/workbench/mixins/websocket'
 import { memberGetLoginInMemberInfoByLdap } from '@/api/projectIndex'
 import { logoutUrl, envUrl } from '@/apiConfig/requestIP.js'
 import { verifyIsAdmin } from '@/api/configure.js'
+
 export default {
   mixins: [websocket],
   data() {
     return {
       size: 'small',
-      headList: routes.filter(item => item.name !== '业务线'),
+      headList: routes.filter((item) => item.name !== '业务线'),
       userInfo: null,
       memberCheck: false,
       target: true,
@@ -144,13 +196,16 @@ export default {
           // 先对父元素进行查找
           this.$store.dispatch('global/setActiveNavTag', element.name)
         } else if (element.children) {
-          const child = element.children.find(item => item.name === routeName) // 对子元素进行查找
-          child ? this.$store.dispatch('global/setActiveNavTag', element.name) : '' // 父元素的名字设为路径
+          const child = element.children.find((item) => item.name === routeName) // 对子元素进行查找
+          child
+            ? this.$store.dispatch('global/setActiveNavTag', element.name)
+            : '' // 父元素的名字设为路径
         }
       }
     },
     // 切换二级导航
     changeNavTag(nav) {
+      window.log({ c: 'entry', d: nav.key })
       this.$store.dispatch('global/setActiveNavTag', nav.name) // 设置二级导航的类别
       this.$router.push({ name: nav.name }) // 跳转
     },
@@ -203,6 +258,9 @@ export default {
         link.href = link.href.replace(/favicon-tips.ico/, 'favicon.ico')
       }
     }
+  },
+  components: {
+    HeaderMenu
   }
 }
 </script>
@@ -210,9 +268,11 @@ export default {
 .mr10 {
   margin-right: 10px;
 }
+
 .mb16 {
   margin-bottom: 16px;
 }
+
 .head-wrapper {
   display: flex;
   flex-direction: column;
@@ -225,16 +285,19 @@ export default {
   color: #333;
   padding-top: 17px;
 }
+
 .head-logo {
   height: 40px;
   width: 40px;
   margin-bottom: 42px;
+
   .svg-icon {
     cursor: pointer;
     width: 100%;
     height: 100%;
   }
 }
+
 .nav-tag {
   width: 100%;
   font-size: 14px;
@@ -243,6 +306,7 @@ export default {
   margin-bottom: 20px;
   padding: 5px 0 9px 0;
   cursor: pointer;
+
   .icon {
     position: relative;
     color: #ffffff;
@@ -251,6 +315,7 @@ export default {
     margin: 7px auto;
     font-size: 32px;
   }
+
   .svg-icon {
     position: absolute;
     top: 0;
@@ -258,30 +323,35 @@ export default {
     width: 100%;
     height: 100%;
   }
+
   .if-notice {
     position: absolute;
     z-index: 1;
     height: 8px;
     width: 8px;
-    background-color: #E02020;
+    background-color: #e02020;
     border-radius: 50%;
     top: 0;
     right: 0;
     transform: translateY(-50%);
   }
 }
+
 .active-nav-tag {
-  background-color: #1E89F7;
+  background-color: #1e89f7;
 }
+
 .nav-tag-type {
   margin-top: auto;
   color: #ffffff;
   cursor: pointer;
 }
+
 .user-tip {
-  margin-top: auto;
+  margin-top: 20px;
   margin-bottom: 20px;
 }
+
 .user-info {
   height: 30px;
   width: 30px;
@@ -293,64 +363,79 @@ export default {
   overflow: hidden;
   // margin-top: auto;
   margin-bottom: 30px;
+
   img {
     height: 30px;
   }
 }
+
 .user-admin-one {
   // height: 190px;
   .title {
     cursor: no-drop;
+
     .icon {
       margin-right: 5px;
       font-size: 12px;
-      color: #409EFF;
+      color: #409eff;
     }
+
     .label {
       color: #444;
       font-size: 14px;
     }
   }
+
   .line {
     margin-bottom: 10px;
     min-height: 21px;
+
     &.clickText {
       cursor: pointer;
       margin-bottom: 16px;
+
       .label {
-        color: #409EFF;
+        color: #409eff;
       }
     }
   }
+
   .item {
     margin-left: 18px;
     cursor: pointer;
+
     .label {
       color: #444;
       font-size: 12px;
+
       .label-text {
         display: inline-block;
         vertical-align: bottom;
-        margin-right: 4px
+        margin-right: 4px;
       }
     }
+
     .fontSize14 {
       font-size: 14px;
     }
   }
+
   .outLogin {
     display: inline-block;
     margin-top: 5px;
+
     .icon {
       display: inline-block;
-      color: #409EFF;
+      color: #409eff;
       font-size: 14px;
     }
+
     .label {
-      color: #409EFF;
+      color: #409eff;
       font-size: 14px;
     }
   }
+
   // width: 95px;
   // display: flex;
   // flex-direction: column;
@@ -383,57 +468,102 @@ export default {
 <style lang="scss" scoped>
 .head-popover {
   box-shadow: 10px 0px 11px #dedede;
+
   /deep/ .ant-popover-inner-content {
     padding: 0;
   }
 }
+
 .nav-div1 {
-  width:25px;height:50px;border-radius: 0 50px 50px 0;line-height:50px;background: #6cb5ff; position: absolute; bottom: 172px; left: 0;border: 1px solid #6cb5ff;animation:myfirsts 0.5s;
+  width: 25px;
+  height: 50px;
+  border-radius: 0 50px 50px 0;
+  line-height: 50px;
+  background: #6cb5ff;
+  position: absolute;
+  bottom: 172px;
+  left: 0;
+  border: 1px solid #6cb5ff;
+  animation: myfirsts 0.5s;
 }
+
 .nav-div2 {
-  bottom: 137px; width:60px; height:120px; line-height:120px;border-radius: 0 80px 80px 0;;background: #6cb5ff; position: absolute; left: 0;animation:myfirst 1s;
+  bottom: 137px;
+  width: 60px;
+  height: 120px;
+  line-height: 120px;
+  border-radius: 0 80px 80px 0;
+  background: #6cb5ff;
+  position: absolute;
+  left: 0;
+  animation: myfirst 1s;
 }
-@keyframes myfirst
-{
-	from {bottom: 172px; width:25px; height:50px; line-height:50px;}
-	to {bottom: 137px; width:60px; height:120px; line-height:120px;}
+
+@keyframes myfirst {
+  from {
+    bottom: 172px;
+    width: 25px;
+    height: 50px;
+    line-height: 50px;
+  }
+  to {
+    bottom: 137px;
+    width: 60px;
+    height: 120px;
+    line-height: 120px;
+  }
 }
 
-@keyframes myfirsts
-{
-	from {bottom: 137px; width:60px; height:120px; line-height:120px;}
-  to {bottom: 172px; width:25px; height:50px; line-height:50px;}
+@keyframes myfirsts {
+  from {
+    bottom: 137px;
+    width: 60px;
+    height: 120px;
+    line-height: 120px;
+  }
+  to {
+    bottom: 172px;
+    width: 25px;
+    height: 50px;
+    line-height: 50px;
+  }
 }
 
 .nav-div3 {
-  width:25px;
-  height:50px;
-  line-height:50px;
-  background: #FFF;
+  width: 25px;
+  height: 50px;
+  line-height: 50px;
+  background: #fff;
   bottom: 172px;
-  border: 1px solid #FFF;
+  border: 1px solid #fff;
   opacity: 0.63;
 }
+
 .nav-div4 {
-  width:20px;
-  height:40px;
-  line-height:45px;
-  background: #FFF;
+  width: 20px;
+  height: 40px;
+  line-height: 45px;
+  background: #fff;
   bottom: 177px;
-  border: 1px solid #FFF;
+  border: 1px solid #fff;
 }
+
 .div-child {
   text-align: right;
   margin-right: 19px;
   line-height: 61px;
   cursor: pointer;
   opacity: 1;
-  animation:myfirs 3s;
+  animation: myfirs 3s;
 }
-@keyframes myfirs
-{
-	from {opacity: 0}
-  to {opacity: 1}
+
+@keyframes myfirs {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
 }
 
 .nav-circular {

+ 149 - 0
src/components/newLayout/components/baseData.js

@@ -0,0 +1,149 @@
+export const menuBaseData = [
+  // 项目管理
+  {
+    name: "项目管理",
+    key: "thothFrontend",
+    path: "http://zhihui.xiaojukeji.com/#/projectManage/projectIndex",
+    menuList: [],
+  },
+  // 环境管理
+  {
+    name: "环境管理",
+    key: "env",
+    path: "http://zhihui-env.intra.xiaojukeji.com/#/env",
+    menuList: [],
+  },
+  // 工具集合
+  {
+    name: "工具集合",
+    key: "tools",
+    path: "",
+    menuList: [
+      {
+        name: "Mock服务",
+        key: "mock",
+        menuBase: {
+          icon: "&#xe60e;",
+          class: "",
+          color: "#F98750",
+        },
+        path: "/mock/dubbomock",
+      },
+      {
+        name: "MQ测试工具",
+        key: "mqTest",
+        path: "/mqTest",
+        desc: "MQ测试工具MQ测试工具MQ测试工具MQ测试工具MQ测试工具MQ测试工具",
+        menuBase: {
+          icon: "&#xe611;",
+          class: "blueGradientColorText", // class 与 color 同时存在,优先使用 class
+          color: "",
+        },
+      },
+      {
+        name: "接口管理",
+        key: "API",
+        desc:
+          "接口管理接口管理接口管理接口管理接口管理接口管理接口管理接口管理接口管理接口管理",
+        blank: "http://zhihui-api.intra.didichuxing.com/",
+        path: "/API",
+        menuBase: {
+          icon: "&#xe613;",
+          class: "violetGradientColorText",
+          color: "",
+        },
+      },
+      {
+        name: "上线质检",
+        key: "online",
+        menuBase: {
+          icon: "&#xe639;",
+          class: "greenGradientColorText",
+          color: "#F98750",
+        },
+        path: "/online/check_list",
+      },
+      {
+        name: "虚拟硬件",
+        key: "virtualDevices",
+        menuBase: {
+          icon: "&#xe60c;",
+          class: "yellowGradientColorText",
+          color: "#F98750",
+        },
+        path: "/virtualDevices/HTvehicle",
+      },
+      {
+        name: "发布管理",
+        key: "newWeb",
+        menuBase: {
+          icon: "&#xe60b;",
+          class: "blueGradientColorText",
+          color: "",
+        },
+        path: "/newWeb",
+      },
+      {
+        name: "端自动化",
+        key: "automation",
+        menuBase: {
+          icon: "&#xe60a;",
+          class: "violetGradientColorText",
+          color: "",
+        },
+        path: "/automation/useCase_list",
+      },
+      {
+        name: "数据中心",
+        key: "data",
+        menuBase: {
+          icon: "&#xe60d2;",
+          class: "greenGradientColorText",
+          color: "",
+        },
+        path: "/data/upload",
+      },
+    ],
+  },
+  // 流量回放
+  // {
+  //   name: "流量回放",
+  //   key: "flowplayback",
+  //   path: "",
+  //   menuList: [],
+  // },
+];
+
+export const envUrl = {
+  thothFrontend: {
+    name: "项目管理",
+    path: {
+      dev: "http://zhihui-test.intra.xiaojukeji.com/#/projectManage/projectIndex",
+      pre: "http://zhihui-pre.intra.xiaojukeji.com/#/projectManage/projectIndex",
+      prod: "http://zhihui.xiaojukeji.com/#/projectManage/projectIndex",
+    },
+  },
+  env: {
+    name: "环境管理",
+    path: {
+      dev: "http://zhihui-test.intra.xiaojukeji.com/zhihui_env/",
+      pre: "http://zhihui-pre.intra.xiaojukeji.com/zhihui_env/",
+      prod: "http://zhihui.xiaojukeji.com/zhihui_env/",
+    },
+  },
+  tools: {
+    name: "工具集合",
+    path: {
+      dev: "http://zhihui-test.intra.xiaojukeji.com/tools/",
+      pre: "http://zhihui-pre.intra.xiaojukeji.com/tools/",
+      prod: "http://zhihui.xiaojukeji.com/tools/",
+    },
+  },
+  // flowplayback: {
+  //   name: "流量回放",
+  //   path: {
+  //     dev: "",
+  //     prod: "",
+  //   },
+  // },
+};

+ 186 - 0
src/components/newLayout/components/menu.vue

@@ -0,0 +1,186 @@
+<template>
+  <a-popover placement="rightBottom" overlay-class-name="head-popover">
+    <!--    <svg-icon class="menu-wrapper-icon" icon-class="question" />-->
+
+    <template slot="content">
+      <div class="menu-wrapper">
+        <div
+          class="children-menu-wrapper"
+          v-for="item in menuBaseData"
+          :key="item.key"
+        >
+          <div
+            class="title"
+            :class="{ active: active === item.key }"
+            @click="switchProjects(item)"
+          >
+            {{ item.name }}
+          </div>
+          <a-row
+            :gutter="[24, 24]"
+            class="box"
+            style="margin: 0"
+            v-if="item.menuList.length"
+          >
+            <a-col
+              v-for="elm in item.menuList"
+              :span="8"
+              class="item-wrapper"
+              @click="goToPage(elm)"
+            >
+              <span class="custom-icon-wrapper">
+                <i
+                  class="iconfont icon"
+                  :class="elm.menuBase.class"
+                  :style="{
+                    fontSize: '20px',
+                    color:
+                      elm.menuBase.color && !elm.menuBase.class
+                        ? elm.menuBase.color
+                        : 'transparent'
+                  }"
+                  >{{ translateHtmlCharater(elm.menuBase.icon) }}</i
+                >
+              </span>
+              <div class="name">{{ elm.name }}</div>
+            </a-col>
+          </a-row>
+        </div>
+      </div>
+    </template>
+    <i class="iconfont icon menu-wrapper-icon">&#x11911;</i>
+  </a-popover>
+</template>
+
+<script>
+import { menuBaseData, envUrl } from './baseData'
+
+Object.freeze(menuBaseData)
+Object.freeze(envUrl)
+export default {
+  name: 'HeaderMenu',
+  data() {
+    return {
+      menuBaseData,
+      envUrl,
+      active: 'thothFrontend',
+      envTag: 'local'
+    }
+  },
+  mounted() {
+    this.getEnvTag()
+  },
+  methods: {
+    // 处理 unicode 无法直接通过变量显示问题
+    translateHtmlCharater(html) {
+      const div = document.createElement('i')
+      div.innerHTML = html
+      return div.textContent
+    },
+    goToPage(item) {
+      window.log({ c: 'top_menu', d: item.key });
+      if (this.envTag !== 'local') {
+        window.open(
+          `${this.envUrl['tools'].path[this.envTag]}#${item.path}`,
+          '_self'
+        )
+      }
+    },
+    switchProjects({ path, key }) {
+      window.log({ c: 'top_menu', d: key })
+      if (this.envTag !== 'local') {
+        let bizId = ''
+        if (key === 'thothFrontend') {
+          bizId = `?bizId=${this.$route.query.bizId}`
+        }
+        window.open(`${envUrl[key].path[this.envTag]}${bizId}`, '_self')
+        return
+      }
+      this.$router.replace({
+        path: '/projectManage/projectIndex',
+        query: { ...this.$route.query }
+      })
+      // this.$router.replace({ path: this.$route.path, query: { ...this.$route.query, page: newV }})
+    },
+    getEnvTag() {
+      const { host } = location
+      if (host.indexOf('localhost') < 0) {
+        this.envTag = 'dev'
+        if (host.indexOf('zhihui-pre.intra.xiaojukeji.com') > -1) {
+          this.envTag = 'pre'
+        }
+        if (host.indexOf('zhihui.xiaojukeji.com') > -1) {
+          this.envTag = 'prod'
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style scoped lang="less">
+.menu-wrapper-icon {
+  font-size: 30px;
+  line-height: 1;
+  color: #ffffff;
+  cursor: pointer;
+  margin: auto auto -5px;
+}
+
+.menu-wrapper {
+  width: 385px;
+
+  .children-menu-wrapper {
+    line-height: initial;
+    margin-top: 12px;
+    font-size: 16px;
+
+    .title {
+      cursor: pointer;
+
+      &:hover {
+        color: #409eff;
+      }
+    }
+
+    .box {
+      line-height: initial;
+
+      .item-wrapper {
+        cursor: pointer;
+        margin-top: 14px;
+        text-align: center;
+        height: 65px;
+
+        .name {
+          margin-top: 6px;
+          font-size: 14px;
+          line-height: 1;
+        }
+
+        .custom-icon-wrapper {
+          position: relative;
+
+          .iconfont {
+            font-size: 20px;
+          }
+
+          .new {
+            position: absolute;
+            top: -12px;
+            right: -19px;
+          }
+        }
+      }
+
+      .hide {
+        display: none;
+      }
+    }
+  }
+
+  .active {
+    color: #409eff;
+  }
+}
+</style>

+ 14 - 10
src/main.js

@@ -6,8 +6,9 @@ import ElementUI from 'element-ui'
 import 'element-ui/lib/theme-chalk/index.css'
 // import locale from 'element-ui/lib/locale/lang/en' // lang i18n 英文
 
-import { DatePicker, Popover } from 'ant-design-vue'
-Vue.use(DatePicker).use(Popover)
+import { DatePicker, Popover, Row, Col } from 'ant-design-vue'
+
+Vue.use(DatePicker).use(Popover).use(Row).use(Col)
 
 import '@/styles/index.scss' // global css
 
@@ -17,20 +18,23 @@ import router from './router'
 
 import '@/icons' // icon
 import htmlToPdf from '@/utils/htmlToPdf'
+
 Vue.use(htmlToPdf)
 
 import animated from 'animate.css'
+
 Vue.use(animated)
 /**
-   * If you don't want to use mock-server
-   * you want to use MockJs for mock api
-   * you can execute: mockXHR()
-   *
-   * Currently MockJs will be used in the production environment,
-   * please remove it before going online! ! !
-   */
+ * If you don't want to use mock-server
+ * you want to use MockJs for mock api
+ * you can execute: mockXHR()
+ *
+ * Currently MockJs will be used in the production environment,
+ * please remove it before going online! ! !
+ */
 
 import axios from 'axios'
+
 Vue.prototype.$http = axios
 
 // set ElementUI lang to EN
@@ -43,5 +47,5 @@ new Vue({
   el: '#app',
   router,
   store,
-  render: h => h(App)
+  render: (h) => h(App)
 })

+ 15 - 0
src/router/newRouter.js

@@ -6,6 +6,7 @@ const layout = [
     component: Layout,
     icon: 'person-workbench',
     redirect: '/workbench/person/personDetail',
+    key: 'self_workbench',
     children: [
       {
         path: 'personDetail',
@@ -21,6 +22,7 @@ const layout = [
     component: Layout,
     icon: 'team-workbench',
     redirect: '/workbench/team/teamDetail',
+    key: 'team_workbench',
     children: [
       {
         path: 'teamDetail',
@@ -50,11 +52,13 @@ const layout = [
     icon: 'project-manage',
     redirect: '/projectManage/projectIndex',
     meta: { title: '项目管理' },
+    key: 'project_management',
     children: [
       {
         path: 'projectIndex',
         name: '项目',
         icon: 'project',
+        key: 'project',
         component: () => import('@/views/projectManage/projectList/projectIndex.vue'),
         meta: { title: '项目' }
       },
@@ -69,6 +73,7 @@ const layout = [
         path: 'requirementIndex',
         name: '需求',
         icon: 'requirement',
+        key: 'requirement',
         component: () => import('@/views/projectManage/requirement/list/index.vue'),
         meta: { title: '需求' }
       },
@@ -83,6 +88,7 @@ const layout = [
         path: 'taskIndex',
         name: '任务',
         icon: 'task',
+        key: 'task',
         component: () => import('@/views/projectManage/taskList/taskIndex'),
         meta: { title: '任务' }
       },
@@ -104,6 +110,7 @@ const layout = [
         path: '/projectManage/bugList/bugindex',
         name: '缺陷',
         icon: 'bug',
+        key: 'bug',
         component: () => import('@/views/projectManage/bugList/bugindex'),
         meta: { title: '缺陷' }
       },
@@ -118,6 +125,7 @@ const layout = [
         path: 'reportManagement',
         name: '报告',
         icon: 'report',
+        key: 'report',
         component: () => import('@/views/reportManagement/testPresentation'),
         meta: { title: '报告' }
       },
@@ -168,6 +176,7 @@ const layout = [
         name: '迭代',
         cutOff: true,
         icon: 'iteration',
+        key: 'iteration',
         component: () => import('@/views/projectManage/iteration/index'),
         meta: { title: '迭代' }
       },
@@ -182,6 +191,7 @@ const layout = [
         path: 'version',
         name: '版本',
         icon: 'version',
+        key: 'version',
         component: () => import('@/views/projectManage/version/list/index.vue'),
         meta: { title: '版本' }
       },
@@ -198,6 +208,7 @@ const layout = [
         name: '线上问题 ',
         icon: 'onlineProblem',
         cutOff: true,
+        key: 'onlineProblem',
         component: () => import('@/views/projectManage/onlineproblem'),
         meta: { title: '线上问题 ' }
       },
@@ -221,6 +232,7 @@ const layout = [
         name: '测试用例',
         icon: 'test-case',
         cutOff: true,
+        key: 'usecase',
         component: () => import('@/views/useCase'),
         meta: { title: '测试用例' }
       },
@@ -242,6 +254,7 @@ const layout = [
         path: 'testPage',
         name: '测试计划',
         icon: 'test-plain',
+        key: 'testplain',
         component: () => import('@/views/Platform/testPage.vue'),
         meta: { title: '测试计划' }
       },
@@ -250,6 +263,7 @@ const layout = [
         name: '统计分析',
         icon: 'statistics',
         cutOff: true,
+        key: 'statistics',
         component: () => import('@/views/quality/allStatistics.vue'),
         meta: { title: '统计分析' }
       },
@@ -335,6 +349,7 @@ const layout = [
         path: 'index',
         name: '配置中心',
         icon: 'config',
+        key: 'config',
         component: () => import('@/views/ToConfigure/index'),
         meta: { title: '配置中心' }
       }

+ 42 - 1
src/styles/index.scss

@@ -54,7 +54,7 @@ div:focus {
     visibility: hidden;
     display: block;
     font-size: 0;
-    content: " ";
+    content: ' ';
     clear: both;
     height: 0;
   }
@@ -96,3 +96,44 @@ div:focus {
   color: #303133;
   padding-left: 10px;
 }
+
+.yellowGradientColorText {
+  background: linear-gradient(45deg, #fcd56e, #f87046);
+  -webkit-background-clip: text;
+}
+
+.blueGradientColorText {
+  background: linear-gradient(45deg, #1ff6ff, #1c84fd);
+  -webkit-background-clip: text;
+}
+
+.greenGradientColorText {
+  background: linear-gradient(45deg, #a3fc2a, #0eb400);
+  -webkit-background-clip: text;
+}
+
+.violetGradientColorText {
+  background: linear-gradient(45deg, #d0adff, #a15dff);
+  -webkit-background-clip: text;
+}
+
+.iconfont {
+  font-family: 'iconfont' !important;
+  font-size: 16px;
+  font-style: normal;
+  color: transparent;
+  -webkit-font-smoothing: antialiased;
+  -webkit-text-stroke-width: 0.2px;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+@font-face {
+  font-family: 'iconfont'; /* project id 2402558 */
+  src: url('//at.alicdn.com/t/font_2402558_4xo0otrcud7.eot');
+  src: url('//at.alicdn.com/t/font_2402558_4xo0otrcud7.eot?#iefix')
+      format('embedded-opentype'),
+    url('//at.alicdn.com/t/font_2402558_4xo0otrcud7.woff2') format('woff2'),
+    url('//at.alicdn.com/t/font_2402558_4xo0otrcud7.woff') format('woff'),
+    url('//at.alicdn.com/t/font_2402558_4xo0otrcud7.ttf') format('truetype'),
+    url('//at.alicdn.com/t/font_2402558_4xo0otrcud7.svg#iconfont') format('svg');
+}

+ 5 - 0
src/views/projectManage/bugList/bugindex.vue

@@ -390,10 +390,14 @@ export default {
     this.$store.state.data.status = false
   },
   methods: {
+    logHandle(d) {
+      window.log({ c: 'bug', d })
+    },
     changeSelect() {
       this.$forceUpdate()
     },
     getBugList() { // 查询功能
+      this.logHandle('get_bug')
       this.$forceUpdate()
       if (!this.stratAndEnd) {
         this.stratAndEnd = []
@@ -461,6 +465,7 @@ export default {
       const res = await taskListCreate(params)
       if (res.code === 200) {
         this.taskEnumList = res.data || []
+        this.logHandle('get_bug')
       }
     },
     bugListSelect() {

+ 2 - 0
src/views/projectManage/projectList/projectIndex.vue

@@ -419,6 +419,7 @@ export default {
         this.table_project = res.data
         this.total = res.total
         this.table_loading = false
+        this.logHandle('get_project')
       })
       settingGetBizList({}).then(res => {
         this.all_bizId = res.data
@@ -497,6 +498,7 @@ export default {
         this.table_project = res.data
         this.total = res.total
         this.table_loading = false
+        this.logHandle('get_project')
       })
       this.isToOne = true
     },

+ 4 - 3
src/views/projectManage/requirement/list/index.vue

@@ -484,14 +484,14 @@ export default {
       this.nowTab = e
       if (this.nowTab === 'charts') {
         this.get_charts()
-        window.log({ c: 'requirement', d: 'changtab_requirement_charts' })
+        this.logHandle('changtab_requirement_charts')
       } else {
         this.chartData = {}
         this.getTableData()
       }
     },
     get_charts() {
-      window.log({ c: 'requirement', d: 'get_requirement_charts' })
+      this.logHandle('get_requirement_charts')
       this.updateChartSearchFormValue()
       this.getSearchFormHandle()
       this.get_chartList()
@@ -539,6 +539,7 @@ export default {
         this.tableData = res.data.list
         this.total = res.data.total
         this.loading = false
+        this.logHandle('get_requirement')
       })
     },
     async get_chartList() {
@@ -558,7 +559,7 @@ export default {
       this.total = dataList.total
       this.tableTitle = dataList.data.title
       this.loading = false
-      window.log({ c: 'requirement', d: 'get_requirement_charts_list_detial' })
+      this.logHandle('get_requirement_charts_list_detial')
     },
     async showRequirementEnum() {
       const res = await showRequirementEnum()

+ 4 - 3
src/views/projectManage/taskList/taskIndex.vue

@@ -482,7 +482,7 @@ export default {
       this.nowTab = e
       if (this.nowTab === 'charts') {
         this.get_charts()
-        window.log({ c: 'task', d: 'changtab_task_charts' })
+        this.logHandle('changtab_task_charts')
       } else {
         this.chartData = {}
         this.get_taskList()
@@ -495,7 +495,7 @@ export default {
       }
     },
     get_charts() {
-      window.log({ c: 'task', d: 'get_task_charts' })
+      this.logHandle('get_task_charts')
       this.updateChartSearchFormValue()
       this.form_taskHandle()
       this.get_chartList()
@@ -517,7 +517,7 @@ export default {
       this.total = dataList.total
       this.tableTitle = dataList.data.title
       this.table_loading = false
-      window.log({ c: 'task', d: 'get_task_charts_list_detial' })
+      this.logHandle('get_task_charts_list_detial')
     },
     test2(item, e) {
       // 获取团队人员信息
@@ -630,6 +630,7 @@ export default {
         this.task_table = res.data
         this.total = res.total
         this.table_loading = false
+        this.logHandle('get_task')
       })
       configShowRequirementVersionEnum({ bizId: this.bizId }).then(res => {
         // 获取需求(查询)

+ 6 - 0
src/views/reportManagement/testPresentation.vue

@@ -245,6 +245,9 @@ export default {
     this.$store.state.data.status = false
   },
   methods: {
+    logHandle(d) {
+      window.log({ c: 'report', d })
+    },
     handleClick(tab, event) {
       this.curIndex = 1
       this.loading = true
@@ -274,6 +277,7 @@ export default {
         if (res.code === 200) {
           this.tableData = res.data
           this.total = res.total
+          this.logHandle('get_report_daily')
         }
       }
       if (this.title === '准出报告') {
@@ -281,6 +285,7 @@ export default {
         if (res.code === 200) {
           this.tableData = res.data.list || []
           this.total = res.data.total
+          this.logHandle('get_report_release')
         }
       }
       if (this.title === '提测报告') {
@@ -290,6 +295,7 @@ export default {
         if (res.code === 200) {
           this.tableData = res.data.list || []
           this.total = res.data.total
+          this.logHandle('get_report_deliver')
         }
       }
       this.loading = false