index.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
  3. <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
  4. <sidebar class="sidebar-container"/>
  5. <div :class="{hasTagsView:needTagsView}" class="main-container">
  6. <div :class="{'fixed-header':fixedHeader}">
  7. <navbar />
  8. <tags-view v-if="needTagsView" />
  9. </div>
  10. <app-main />
  11. <right-panel>
  12. <settings />
  13. </right-panel>
  14. <div class="qw-im">
  15. <el-badge :value="totalUnreadCount" :max="99" :hidden="totalUnreadCount < 1">
  16. <img alt="" class="qw-im-img" @click="() => {this.qw.open = !this.qw.open}" src="../assets/image/chat_icon44.png"/>
  17. <div class="qw-im-text">IM聊天</div>
  18. </el-badge>
  19. </div>
  20. </div>
  21. <el-dialog append-to-body
  22. :width="qw.isMaximized ? '100vw' : '90vw'"
  23. custom-class="im-dialog"
  24. :fullscreen="qw.isMaximized"
  25. :visible.sync="qw.open"
  26. :style="{visibility: !qw.initLoad ? 'hidden' : 'unset'}"
  27. :modal="qw.initLoad"
  28. :title="qw.title">
  29. <div class="qw-im-content">
  30. <QwIM :showQw="qw.open" :isMaximized="qw.isMaximized" @close="() => qw.open = false"/>
  31. </div>
  32. </el-dialog>
  33. </div>
  34. </template>
  35. <script>
  36. import RightPanel from '@/components/RightPanel'
  37. import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
  38. import ResizeMixin from './mixin/ResizeHandler'
  39. import { mapState } from 'vuex'
  40. import variables from '@/assets/styles/variables.scss'
  41. import QwIM from '@/views/qw/qwChat/qq.vue'
  42. export default {
  43. name: 'Layout',
  44. components: {
  45. AppMain,
  46. Navbar,
  47. RightPanel,
  48. Settings,
  49. Sidebar,
  50. TagsView,
  51. QwIM
  52. },
  53. mixins: [ResizeMixin],
  54. computed: {
  55. ...mapState({
  56. theme: state => state.settings.theme,
  57. sideTheme: state => state.settings.sideTheme,
  58. sidebar: state => state.app.sidebar,
  59. device: state => state.app.device,
  60. needTagsView: state => state.settings.tagsView,
  61. fixedHeader: state => state.settings.fixedHeader,
  62. companyUser:state => state.user.user,
  63. totalUnreadCount: state => state.qwIm.totalUnreadCount
  64. }),
  65. classObj() {
  66. return {
  67. hideSidebar: !this.sidebar.opened,
  68. openSidebar: this.sidebar.opened,
  69. withoutAnimation: this.sidebar.withoutAnimation,
  70. mobile: this.device === 'mobile'
  71. }
  72. },
  73. variables() {
  74. return variables;
  75. }
  76. },
  77. data() {
  78. return {
  79. qw: {
  80. open: false,
  81. title: '',
  82. isMaximized: false,
  83. initLoad: false
  84. }
  85. }
  86. },
  87. mounted() {
  88. if (!this.qw.initLoad) {
  89. this.qw.open = true
  90. this.$nextTick(() => {
  91. this.qw.open = false
  92. setTimeout(() => {
  93. this.qw.initLoad = true
  94. }, 500)
  95. })
  96. }
  97. },
  98. methods: {
  99. handleClickOutside() {
  100. this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
  101. }
  102. }
  103. }
  104. </script>
  105. <style lang="scss" scoped>
  106. @import "~@/assets/styles/mixin.scss";
  107. @import "~@/assets/styles/variables.scss";
  108. .app-wrapper {
  109. @include clearfix;
  110. position: relative;
  111. height: 100%;
  112. width: 100%;
  113. &.mobile.openSidebar {
  114. position: fixed;
  115. top: 0;
  116. }
  117. }
  118. .drawer-bg {
  119. background: #000;
  120. opacity: 0.3;
  121. width: 100%;
  122. top: 0;
  123. height: 100%;
  124. position: absolute;
  125. z-index: 999;
  126. }
  127. .fixed-header {
  128. position: fixed;
  129. top: 0;
  130. right: 0;
  131. z-index: 9;
  132. width: calc(100% - #{$base-sidebar-width});
  133. transition: width 0.28s;
  134. }
  135. .hideSidebar .fixed-header {
  136. width: calc(100% - 54px)
  137. }
  138. .mobile .fixed-header {
  139. width: 100%;
  140. }
  141. ::v-deep .qw-im {
  142. z-index: 2000;
  143. position: fixed;
  144. right: 30px;
  145. bottom: 30px;
  146. width: 108px;
  147. height: 108px;
  148. text-align: center;
  149. background: linear-gradient( 135deg, #006CFF 0%, #68B1FF 100%);
  150. border-radius: 54px 54px 54px 54px;
  151. display: flex;
  152. align-items: center;
  153. justify-content: center;
  154. flex-direction: column;
  155. .qw-im-img {
  156. width: 44px;
  157. }
  158. .qw-im-text{
  159. font-weight: 600;
  160. font-size: 16px;
  161. color: #FFFFFF;
  162. }
  163. .el-badge__content {
  164. border: unset;
  165. }
  166. }
  167. ::v-deep .im-dialog {
  168. max-width: 100vw;
  169. max-height: 100vh;
  170. .el-dialog__header {
  171. display: none;
  172. }
  173. .el-dialog__body {
  174. padding: 0 !important;
  175. }
  176. &:not(.is-fullscreen) {
  177. top: 50% !important;
  178. transform: translateY(-50%) !important;
  179. margin-top: 0 !important;
  180. }
  181. }
  182. .qw-im-content {
  183. width: 100%;
  184. height: 100%;
  185. /* 可选:让内容区自动撑满弹窗 */
  186. display: flex;
  187. flex-direction: column;
  188. }
  189. </style>