index.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <template>
  2. <div class="menu-con" :key="id" :style="{left:deviation+'px'}">
  3. <template v-if="isShowScroll">
  4. <i class="iconfont icon_back" @click="moveSlide('forward')"></i>
  5. <i class="iconfont icon_forward" @click="moveSlide('back')"></i>
  6. <span class="addBtn" @click="$emit('addGroup')" v-if="!hiddenHover">
  7. <i class="iconfont icon_plus"></i>
  8. </span>
  9. </template>
  10. <div class="menu sub-menu" :class="(!isShowScroll&&!deviation?'sm-active ':(cls?'':'addBef')) + ' ' + `${cls}`" :id="id">
  11. <ul class="mytablist" :id="subId" :style="{ left: oneLeft + 'px' }">
  12. <li
  13. :title="item.name"
  14. v-for="(item, i) in list"
  15. :class="{ active: item.id == active.id,hidden:hiddenHover }"
  16. @click="$emit('clickItem',item)"
  17. :key="i"
  18. >
  19. {{ item.name }}
  20. <div
  21. class="oper"
  22. @click.stop
  23. @mouseleave="handleleave"
  24. @mouseenter="handleover"
  25. >
  26. <i class="iconfont iconmore"></i>
  27. <slot name="hover" :item="item">
  28. </slot>
  29. </div>
  30. </li>
  31. <li
  32. v-if="!hiddenHover&&!isShowScroll"
  33. class="li-add"
  34. @click="$emit('addGroup')"
  35. >
  36. <i class="iconfont icon_plus"></i>
  37. </li>
  38. </ul>
  39. </div>
  40. </div>
  41. </template>
  42. <script>
  43. const RANGE = 60
  44. export default {
  45. data(){
  46. return {
  47. hasLoad:false
  48. }
  49. },
  50. props: {
  51. list: {
  52. default() {
  53. return [];
  54. },
  55. type: Array,
  56. },
  57. cls:String,
  58. subId:String,
  59. id:String,
  60. deviation:Number,
  61. active:Object | Array,
  62. hiddenHover:Boolean
  63. },
  64. computed:{
  65. },
  66. mounted(){
  67. this.refreshScroll()
  68. if (!this.hasLoad) {
  69. this.$nextTick(()=>{
  70. this.refreshScroll()
  71. this.hasLoad=true
  72. })
  73. }
  74. },
  75. watch: {
  76. '$route.name':function (newVal) {
  77. if (newVal) {
  78. this.refreshScroll()
  79. }
  80. },
  81. list:function () {
  82. this.refreshScroll()
  83. }
  84. },
  85. methods:{
  86. refreshScroll(){
  87. this.$nextTick(()=>{
  88. this.oneLeft = 0
  89. if (document.querySelector('#'+this.subId)) {
  90. this.oneWidth = document.querySelector('#'+this.subId).offsetWidth
  91. this.menuWidth = document.querySelector('#'+this.id).offsetWidth
  92. console.log(this.menuWidth,this.oneLeft, this.oneWidth);
  93. this.isShowScroll = this.oneWidth + 40 > this.menuWidth
  94. }
  95. })
  96. },
  97. moveSlide(type) {
  98. if (type == 'back') {
  99. console.log(this.menuWidth,this.oneLeft, this.oneWidth);
  100. if ((this.menuWidth - this.oneLeft) > this.oneWidth) {
  101. return
  102. }
  103. }
  104. else{
  105. if (this.oneLeft>=0) {
  106. this.oneLeft=0
  107. return
  108. }
  109. }
  110. let del = type == 'back'?-RANGE:RANGE
  111. this.oneLeft+=del
  112. },
  113. handleover(e) {
  114. this.currentXY = { top: e.y, left: e.x };
  115. let ul = $(e.target).find("ul");
  116. ul.css({
  117. top: (e.y - 5) + "px",
  118. left: (e.x - 5) + "px",
  119. display: "block",
  120. });
  121. },
  122. handleleave(e) {
  123. let ul = $(e.target).find("ul");
  124. ul.hide();
  125. },
  126. },
  127. data() {
  128. return {
  129. oneLeft:0,
  130. oneWidth:0,
  131. menuWidth:0,
  132. isShowScroll:false
  133. };
  134. },
  135. };
  136. </script>
  137. <style lang="less" scoped>
  138. .menu-con {
  139. width: 100%;
  140. position: relative;
  141. .addBtn{
  142. background-color: @color;
  143. width: 30px;
  144. min-width: unset;
  145. max-width: 30px;
  146. height: 30px;
  147. color: #fff;
  148. padding: 0;
  149. position: absolute;
  150. cursor: pointer;
  151. border-radius: 2px;
  152. right: -40px;
  153. >i{
  154. position: absolute;
  155. top: 50%;
  156. left: 50%;
  157. transform: translate(-50%, -50%);
  158. font-size: 26px;
  159. }
  160. }
  161. > .iconfont {
  162. left: 10px;
  163. top: 8px;
  164. position: absolute;
  165. cursor: pointer;
  166. }
  167. > .icon_forward {
  168. right: 10px;
  169. left: auto;
  170. }
  171. .sub-menu {
  172. max-width: calc(100% - 70px);
  173. position: relative;
  174. overflow: hidden;
  175. height: 40px;
  176. margin: 0 auto;
  177. > ul {
  178. max-width: unset;
  179. overflow: unset;
  180. position: absolute;
  181. left: 0;
  182. transition: 0.3s ease all;
  183. .fixed {
  184. position: absolute;
  185. right: 0;
  186. }
  187. // &::before{
  188. // width: calc(100% - 70px);
  189. // height: calc(100% - 10px);
  190. // pointer-events: none;
  191. // content: '';
  192. // background: linear-gradient(to right,rgba(#fff,0) 0%,rgba(#fff,0) 98%,rgba(#000,1) 100%);
  193. // position: absolute;
  194. // top: 0;
  195. // left: 0;
  196. // z-index: 999;
  197. // display: inline-block;
  198. // }
  199. }
  200. }
  201. .addBef{
  202. position: relative;
  203. &::before{
  204. position: absolute;
  205. right: 0;
  206. top: 0;
  207. content: '';
  208. display: inline-block;
  209. width: 40px;
  210. height: 30px;
  211. z-index: 999;
  212. pointer-events: none;
  213. background: linear-gradient(to right, rgba(0,0,0,0), #161a1a);
  214. }
  215. }
  216. .sm-active{
  217. max-width: 100%;
  218. }
  219. }
  220. </style>