Просмотр исходного кода

Header: Hot And Message And Dcuc

caiaa 1 год назад
Родитель
Сommit
c9b4595749

+ 8 - 0
src/api/business.js

@@ -16,6 +16,14 @@ export function fetchMyBizList(data) {
   })
 }
 
+// 单个收藏
+export function pushAddBizFavorite(appId, id) {
+  return request({
+    url: `business/install/${appId}/${id}`
+  })
+}
+
+// 批量收藏
 export function pushSaveFavorite(data) {
   return request({
     url: 'business/batchUpdate',

+ 8 - 0
src/api/system.js

@@ -16,6 +16,14 @@ export function fetchMySystemList(data) {
   })
 }
 
+// 单个收藏
+export function pushAddFavorite(id) {
+  return request({
+    url: `app/install/${id}`
+  })
+}
+
+// 批量收藏
 export function pushSaveFavorite(data) {
   return request({
     url: 'app/batchUpdate',

+ 373 - 17
src/layout/components/HeaderTop.vue

@@ -14,19 +14,63 @@
     </div>
     <div class="header-right">
       <div class="right-top">
-        <el-popover class="right-top-item" placement="bottom-start" width="400" trigger="click" @show="showData">
-          <el-row v-for="item in gridData" :key="item.id">item.title</el-row>
+        <el-popover v-model="hotVisibile" class="right-top-item" placement="bottom-start" popper-class="hot-popper-box" width="420" trigger="click" @show="showHotPopover">
+          <el-tabs v-model="curHotTab" @tab-click="getHotData">
+            <el-tab-pane label="热门应用" name="hotSys">
+              <div style="margin-bottom: 5px;">提示:根据应用浏览数量排行</div>
+              <div v-loading="sysLoading" class="top-item-box">
+                <div v-for="(item, index) in sysTopData" :key="item.id" class="top-item">
+                  <span :class="['top-rank', index<=2 ? 'top-rank_'+index : '']">{{ index + 1 }}</span>
+                  <span>
+                    <el-avatar :size="32" fit="fill" :src="item.icon | formatFileUrl" />
+                  </span>
+                  <ellipsis-tooltip :content="item.systemName" placement="top" class="top-name" width="200px">
+                    <a @click="$jumpTo('app', item.id, item.systemNumber, item.url)">{{ item.systemName }}</a>
+                  </ellipsis-tooltip>
+                  <span class="top-count"><svg-icon icon-class="remen" class="hot-icon" />{{ formatCount(item.hits) }}</span>
+                  <el-button v-if="item.isFavorite" type="primary" size="small" style="width:68px; cursor: default">已收藏</el-button>
+                  <el-button v-else size="small" style="width:68px" @click="addSysFavorite(item.id, index)">收藏</el-button>
+                </div>
+                <div class="more-item"><span style="cursor: pointer;" @click="showMoreHot('sys')">查看更多</span></div>
+              </div>
+            </el-tab-pane>
+            <el-tab-pane label="热门业务" name="hotBiz">
+              <div style="margin-bottom: 5px;">提示:根据业务浏览数量排行</div>
+              <div v-loading="bizLoading" class="top-item-box">
+                <div v-for="(item, index) in bizTopData" :key="item.id" class="top-item">
+                  <span :class="['top-rank', index<=2 ? 'top-rank_'+index : '']">{{ index + 1 }}</span>
+                  <ellipsis-tooltip :content="item.businessName" placement="top" class="top-name" width="200px">
+                    <a @click="$jumpTo('business', item.id, item.businessNumber, item.url)">{{ item.businessName }}</a>
+                  </ellipsis-tooltip>
+                  <span class="top-count"><svg-icon icon-class="remen" class="hot-icon" />{{ formatCount(item.hits) }}</span>
+                  <el-button v-if="item.isFavorite" type="primary" size="small" style="width:68px; cursor: default">已收藏</el-button>
+                  <el-button v-else size="small" style="width:68px" @click="addBizFavorite(item.appId, item.id, index)">收藏</el-button>
+                </div>
+                <div class="more-item"><span style="cursor: pointer;" @click="showMoreHot('biz')">查看更多</span></div>
+              </div>
+            </el-tab-pane>
+          </el-tabs>
           <div slot="reference"><svg-icon icon-class="yingyong" /><span class="item-title">应用热榜推荐</span></div>
         </el-popover>
         <div class="right-top-item"><svg-icon icon-class="quanxian" /><span class="item-title">个性化设置</span></div>
-        <div class="right-top-item"><svg-icon icon-class="quanxian" /><span class="item-title">用户权限管理</span></div>
-        <div class="right-top-item">
-          <el-badge :value="messageCount.todo" class="badge-item"><svg-icon icon-class="xiaoxi" /></el-badge>
-          <span class="item-title">消息提醒</span>
-        </div>
+        <div class="right-top-item" @click="openRoleSystem"><svg-icon icon-class="quanxian" /><span class="item-title">用户权限管理</span></div>
+        <el-popover v-model="msgVisible" class="right-top-item" placement="bottom" popper-class="msg-popper-box" width="420" trigger="click" @show="showMsgPopover">
+          <el-tabs v-model="curMsgTab" v-loading="msgLoading" @tab-click="getMsgData">
+            <el-tab-pane v-for="type in msgTypeData" :key="type.id" :label="type.label" :name="type.id+''">
+              <div v-for="item in msgData" :key="item.id" class="top-item">
+                <span>{{ item.title }}</span>
+              </div>
+            </el-tab-pane>
+          </el-tabs>
+          <div class="more-item"><span style="cursor: pointer;" @click="showMoreMsg">查看更多</span></div>
+          <div slot="reference">
+            <el-badge :value="messageCount.todo" class="badge-item"><svg-icon icon-class="xiaoxi" /></el-badge>
+            <span class="item-title">消息提醒</span>
+          </div>
+        </el-popover>
         <div class="right-top-item"><svg-icon icon-class="quanxian" /><span class="item-title">换肤</span></div>
         <div class="right-top-item"><svg-icon icon-class="quanxian" /><span class="item-title">意见建议</span></div>
-        <el-popover placement="bottom-end" trigger="click" popper-class="profile-poper-box" class="right-top-item">
+        <el-popover placement="bottom-end" trigger="click" popper-class="profile-popper-box" class="right-top-item">
           <div>
             <div class="avatar-box">
               <el-avatar :size="56" src="/images/avatar.png" />
@@ -67,18 +111,40 @@
 </template>
 
 <script>
+import { hasValidRecords } from '@/utils/convert'
+import { formatCount } from '@/utils'
+
+import { fetchAllSystemList, pushAddFavorite } from '@/api/system'
+import { fetchAllBizList, pushAddBizFavorite } from '@/api/business'
+import { fetchTableList } from '@/api/message'
+
 import { mapGetters } from 'vuex'
-// import { removeCookies } from '@/utils/auth'
 import Search from '@/components/HeaderSearch'
+import EllipsisTooltip from '@/components/EllipsisTooltip'
 
 export default {
+  name: 'HeaderTop',
   components: {
-    Search
+    Search,
+    EllipsisTooltip
   },
   data() {
     return {
-      userName: '',
-      gridData: []
+      // 热门应用推荐
+      hotVisibile: false,
+      curHotTab: 'hotSys',
+      sysTopData: [],
+      bizTopData: [],
+      sysLoading: false,
+      bizLoading: false,
+      isHotInited: false,
+      // 消息提醒
+      msgVisible: false,
+      msgTypeData: [{ 'id': 0, 'label': '待办消息' }, { 'id': 5, 'label': '通知消息' }, { 'id': 6, 'label': '超期提醒消息' }],
+      curMsgTab: '',
+      msgData: [],
+      isMsgInited: false,
+      msgLoading: false
     }
   },
   computed: {
@@ -105,12 +171,302 @@ export default {
         })
       })
     },
-    showData() {
-      this.gridData = [{
-        id: 1,
-        title: 'aaa'
-      }]
+    showHotPopover() {
+      if (!this.isHotInited) {
+        this.getHotData()
+        this.isHotInited = true
+      }
+    },
+    showMoreHot(path) {
+      this.hotVisibile = false
+      this.$router.push(`/${path}`)
+    },
+    getHotData() {
+      const params = {
+        page: 1,
+        size: 5,
+        order: 'hits',
+        params: {
+          delFlag: 0
+        }
+      }
+      if (this.curHotTab === 'hotSys') {
+        this.sysLoading = true
+        fetchAllSystemList(params).then(response => {
+          if (hasValidRecords(response)) {
+            this.sysTopData = response.data.records
+          } else {
+            this.sysTopData = []
+          }
+          this.sysLoading = false
+        }).catch(error => {
+          console.log(error)
+          this.sysLoading = false
+          this.$message({
+            type: 'error',
+            duration: 0,
+            showClose: true,
+            message: '获取热门应用出错:' + error.message
+          })
+        })
+      } else {
+        this.bizLoading = true
+        fetchAllBizList(params).then(response => {
+          if (hasValidRecords(response)) {
+            this.bizTopData = response.data.records
+          } else {
+            this.bizTopData = []
+          }
+          this.bizLoading = false
+        }).catch(error => {
+          console.log(error)
+          this.bizLoading = false
+          this.$message({
+            type: 'error',
+            duration: 0,
+            showClose: true,
+            message: '获取热门业务出错:' + error.message
+          })
+        })
+      }
+    },
+    addSysFavorite(id, index) {
+      this.sysLoading = true
+      pushAddFavorite(id).then(res => {
+        this.sysTopData[index].isFavorite = true
+        this.sysLoading = false
+        this.$message({
+          type: 'success',
+          message: '收藏成功!'
+        })
+      }).catch(error => {
+        console.log(error)
+        this.sysLoading = false
+        this.$message({
+          type: 'error',
+          duration: 0,
+          showClose: true,
+          message: '收藏出错:' + error.message
+        })
+      })
+    },
+    addBizFavorite(appId, id, index) {
+      this.bizLoading = true
+      pushAddBizFavorite(appId, id).then(res => {
+        this.bizTopData[index].isFavorite = true
+        this.bizLoading = false
+        this.$message({
+          type: 'success',
+          message: '收藏成功!'
+        })
+      }).catch(error => {
+        console.log(error)
+        this.bizLoading = false
+        this.$message({
+          type: 'error',
+          duration: 0,
+          showClose: true,
+          message: '收藏出错:' + error.message
+        })
+      })
+    },
+    openRoleSystem() {
+      window.open(this.$store.getters.links.dcucUrl, '_blank')
+    },
+    showMsgPopover() {
+      if (!this.isMsgInited) {
+        this.isMsgInited = true
+        this.getMsgData()
+      }
+    },
+    getMsgData() {
+      this.msgLoading = true
+      const params = {
+        current: 1,
+        size: 5,
+        delFlag: 0,
+        readStatus: 0,
+        messageType: this.curMsgTab === '0' ? '' : this.curMsgTab
+      }
+      fetchTableList(params).then(response => {
+        if (hasValidRecords(response)) {
+          this.msgData = response.data.records
+        } else {
+          this.msgData = []
+        }
+        this.msgLoading = false
+      }).catch(error => {
+        console.log(error)
+        this.msgLoading = false
+        this.$message({
+          type: 'error',
+          duration: 0,
+          showClose: true,
+          message: '获取消息列表出错: ' + error.message
+        })
+      })
+    },
+    showMoreMsg() {
+      this.msgVisible = false
+      this.$router.push('/home')
+    },
+    formatCount(count) {
+      return formatCount(count)
     }
   }
 }
 </script>
+
+<style lang="scss" scoped>
+
+.profile-popper-box {
+  .avatar-box {
+    display: flex;
+    align-items: center;
+
+    .name-box {
+      margin-left: 10px;
+    }
+
+    .user-name {
+      font-size: 14px;
+      color: rgba(0, 0, 0, 0.85);
+      font-weight: bold;
+    }
+
+    .dept-name {
+      font-size: 12px;
+      color: rgba(0, 0, 0, 0.45);
+      margin-top: 5px;
+    }
+  }
+
+  .log-box {
+    border-top: dashed 1px rgba(0, 0, 0, 0.09);
+    border-bottom: dashed 1px rgba(0, 0, 0, 0.09);
+    padding: 5px 0;
+    margin: 10px;
+
+    &>div {
+      padding: 5px 0;
+    }
+
+    .log-left {
+      display: inline-block;
+      width: 100px;
+      text-align: right;
+      color: rgba(0, 0, 0, 0.45);
+    }
+
+    .log-right {
+      color: rgba(0, 0, 0, 0.85);
+    }
+  }
+}
+
+.hot-popper-box, .msg-popper-box {
+  .el-tabs {
+    font-size: 14px;
+    margin-top: -12px !important;
+
+    ::v-deep {
+      .el-tabs__item {
+        font-size: 16px !important;
+
+        &.is-active {
+          font-weight: bold;
+        }
+      }
+    }
+  }
+
+  .more-item {
+    text-align: center;
+    color: rgba(0,0,0,0.45);
+    padding-top: 10px;
+    border-top: 1px dashed rgba(0,0,0,0.09);;
+  }
+}
+
+.hot-popper-box {
+  .top-item-box {
+    .top-item {
+      height: 50px;
+      color: rgba(0,0,0,0.85);
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      &>* {
+        display: inline-block;
+      }
+      &>*+* {
+        margin-left: 10px;
+      }
+      .top-rank {
+        width: 20px;
+        text-align: center;
+      }
+      .top-rank_0 {
+        background-color: #F63842;
+        border-radius: 1px;
+        color: #f0f0f0;
+      }
+      .top-rank_1 {
+        background-color: #FB982D;
+        border-radius: 1px;
+        color: #f0f0f0;
+      }
+      .top-rank_2 {
+        background-color: #FADB14;
+        border-radius: 1px;
+        color: #8e8686;
+      }
+
+      .top-name {
+        width: 270px;
+        margin-bottom: 5px;
+      }
+      .top-count{
+        color: #FF5030;
+      }
+      .hot-icon {
+        margin-right: 5px;
+      }
+    }
+  }
+}
+
+.msg-popper-box {
+  .el-tabs {
+    ::v-deep {
+      .el-tabs__header {
+        margin-bottom: 5px !important;
+      }
+    }
+  }
+
+  .top-item {
+    height: 30px;
+    line-height: 30px;
+    color: rgba(0,0,0,0.85);
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
+
+    &:before{
+      content: '';
+      display: inline-block;
+      background-color: red;
+      width:4px;
+      height:4px;
+      border-radius: 50%;
+      vertical-align: middle;
+    }
+
+    &>span {
+      padding-left: 5px;
+    }
+  }
+}
+</style>

+ 1 - 0
src/store/getters.js

@@ -10,6 +10,7 @@ const getters = {
   idCard: state => state.user.userInfo.idCard,
   deptName: state => state.user.userInfo.deptName,
   userInfo: state => state.user.userInfo,
+  links: state => state.user.links,
   permission_routes: state => state.permission.routes,
   messageCount: state => state.message.message,
   systemCount: state => state.message.system

+ 7 - 2
src/store/modules/user.js

@@ -6,7 +6,8 @@ const getDefaultState = () => {
   return {
     token: getToken(),
     userInfo: {},
-    roles: []
+    roles: [],
+    links: {}
   }
 }
 
@@ -24,6 +25,9 @@ const mutations = {
   },
   SET_ROLES: (state, roles) => {
     state.roles = roles
+  },
+  SET_LINKS: (state, links) => {
+    state.links = links
   }
 }
 
@@ -50,7 +54,7 @@ const actions = {
           return reject('Verification failed, please Login again.')
         }
 
-        const { userInfo, roles } = data
+        const { userInfo, roles, links } = data
 
         // roles must be a non-empty array
         if (!roles || roles.length <= 0) {
@@ -59,6 +63,7 @@ const actions = {
 
         commit('SET_ROLES', roles)
         commit('SET_USER_INFO', userInfo)
+        commit('SET_LINKS', links)
         resolve(data)
       }).catch(error => {
         reject(error)

+ 0 - 45
src/styles/headertop.scss

@@ -111,49 +111,4 @@ $headerTextColor: #ffffff;
       }
     }
   }
-}
-
-.profile-poper-box {
-  .avatar-box {
-    display: flex;
-    align-items: center;
-
-    .name-box {
-      margin-left: 10px;
-    }
-
-    .user-name {
-      font-size: 14px;
-      color: rgba(0, 0, 0, 0.85);
-      font-weight: bold;
-    }
-
-    .dept-name {
-      font-size: 12px;
-      color: rgba(0, 0, 0, 0.45);
-      margin-top: 5px;
-    }
-  }
-
-  .log-box {
-    border-top: dashed 1px rgba(0, 0, 0, 0.09);
-    border-bottom: dashed 1px rgba(0, 0, 0, 0.09);
-    padding: 5px 0;
-    margin: 10px;
-
-    &>div {
-      padding: 5px 0;
-    }
-
-    .log-left {
-      display: inline-block;
-      width: 100px;
-      text-align: right;
-      color: rgba(0, 0, 0, 0.45);
-    }
-
-    .log-right {
-      color: rgba(0, 0, 0, 0.85);
-    }
-  }
 }

+ 0 - 3
src/views/application/index.vue

@@ -202,11 +202,8 @@ export default {
       this.loading = true
       fetchFileList(params).then(response => {
         if (hasValidRecords(response)) {
-          console.log(response.data)
           this.tableData = response.data.records
-          console.log(this.tableData)
           this.total = response.data.total
-          console.log(this.total)
         } else {
           this.tableData = []
           this.total = 0

+ 1 - 1
src/views/business/index.vue

@@ -42,7 +42,7 @@
               </div>
               <div class="item-content">
                 <div class="item-content-left">
-                  <el-avatar :size="56" :src="item.icon | formatFileUrl" />
+                  <!-- <el-avatar :size="56" :src="item.icon | formatFileUrl" /> -->
                   <div class="item-title">
                     <div class="item-name">{{ item.businessName }}</div>
                     <div class="item-system">{{ item.appName }}</div>

+ 3 - 2
src/views/home/Search.vue

@@ -1,7 +1,7 @@
 <template>
   <div>
     <el-row type="flex" justify="center" class="searh-row">
-      <el-col :span="10"><el-input v-model="searchText" placeholder="请输入搜索内容" /></el-col>
+      <el-col :span="10"><el-input v-model="searchText" placeholder="请输入搜索内容" clearable /></el-col>
       <el-col :span="2"><el-button type="primary" icon="el-icon-search" @click="eagleSearch">智搜</el-button></el-col>
     </el-row>
   </div>
@@ -20,7 +20,8 @@ export default {
   methods: {
     eagleSearch() {
       if (!isNull(this.searchText)) {
-        this.$alert(this.$store.state.user.encryptIdCard + '-' + this.searchText)
+        const url = this.$store.getters.links.esouUrl
+        window.open(url.replace('{QUERY}', this.searchText), '_blank')
       } else {
         this.$message({
           type: 'info',