head.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <div
  3. class="head"
  4. data-tauri-drag-region
  5. >
  6. <div
  7. ref="scrollItem"
  8. class="head-items"
  9. >
  10. <template
  11. v-for="(item, index) in list"
  12. :key="index"
  13. >
  14. <div
  15. class="head-items-item"
  16. :class="{ active: index === selectTab }"
  17. @click.stop="e => onChange(index, 'change')"
  18. >
  19. <div>
  20. <div>
  21. <Icon
  22. :name="item.icon"
  23. :size="item.size"
  24. />
  25. {{ item.label }}
  26. </div>
  27. <Icon
  28. :style="`opacity:${index === 0 ? 0 : 1} ;`"
  29. name="close"
  30. :size="12"
  31. @click.stop="onChange(index, 'del')"
  32. />
  33. </div>
  34. </div>
  35. </template>
  36. </div>
  37. <div
  38. class="head-add"
  39. @click="emit('update:showAdd', true)"
  40. >
  41. <Icon
  42. name="add"
  43. :size="15"
  44. />
  45. </div>
  46. </div>
  47. </template>
  48. <script setup lang='ts'>
  49. import { ref, watch } from 'vue'
  50. import { FormData } from '@/components/edit.vue'
  51. const props = withDefaults(defineProps<{
  52. showAdd?: boolean,
  53. list: FormData[],
  54. selectTab: number
  55. }>(), {
  56. showAdd: false,
  57. selectTab: 0,
  58. list: () => []
  59. })
  60. const scrollItem = ref()
  61. const emit = defineEmits<{(evt: 'update:showAdd', value: boolean): void,
  62. (evt: 'update:list', value: FormData[]): void,
  63. (evt: 'onChange', value: { id: number, type: string }): void,
  64. }>()
  65. function onChange(id: number, type: string) {
  66. if (id === 0 && type === 'del') return
  67. emit('onChange', { id, type })
  68. }
  69. watch(() => props.selectTab, (v) => {
  70. setTimeout(() => {
  71. // 滚动
  72. const dom = scrollItem.value.children[v]
  73. const scrollNum = dom.offsetLeft - scrollItem.value.offsetWidth / 2 + dom.offsetWidth / 2
  74. scrollItem.value.scrollLeft = scrollNum
  75. }, 0)
  76. })
  77. </script>
  78. <style lang="scss" scoped>
  79. .head {
  80. width: 100%;
  81. height: 38px;
  82. user-select: none;
  83. text-shadow: 0px -2px -4px var(--shadow-color);
  84. display: flex;
  85. align-items: flex-end;
  86. background: #ccc;
  87. overflow: hidden;
  88. color: var(--font-color);
  89. &-items {
  90. max-width: 85%;
  91. margin-left: 70px;
  92. display: flex;
  93. align-items: flex-end;
  94. overflow-x: auto;
  95. scroll-behavior: smooth;
  96. padding: 0 12px;
  97. cursor: pointer;
  98. /* 隐藏滚动条 */
  99. &::-webkit-scrollbar {
  100. width: 0 !important;
  101. display: none;
  102. }
  103. &-item {
  104. height: 34px;
  105. font-size: 13px;
  106. color: var(--font-color);
  107. padding: 6px 8px 0 8px;
  108. position: relative;
  109. &>div {
  110. display: flex;
  111. align-items: center;
  112. justify-content: space-between;
  113. &>svg {
  114. margin-top: 2px;
  115. margin-left: 3px;
  116. cursor: pointer;
  117. }
  118. &>div {
  119. display: flex;
  120. align-items: center;
  121. &>svg {
  122. margin-right: 5px;
  123. }
  124. }
  125. }
  126. &::after {
  127. content: '';
  128. height: 15px;
  129. width: 2px;
  130. border-radius: 3px;
  131. background: #ddd;
  132. position: absolute;
  133. right: -2px;
  134. top: 50%;
  135. transform: translate(0, -50%);
  136. }
  137. }
  138. .active {
  139. background: white;
  140. border-radius: 8px 8px 0 0;
  141. position: relative;
  142. box-shadow: 8px 8px 0 0 #ffffff, -8px 8px 0 0 #ffffff;
  143. &::before {
  144. content: '';
  145. position: absolute;
  146. left: -8px;
  147. bottom: 0;
  148. width: 8px;
  149. height: 33px;
  150. background: #ccc;
  151. border-radius: 0 0 8px 0;
  152. }
  153. &::after {
  154. content: '';
  155. position: absolute;
  156. right: -8px;
  157. bottom: 0;
  158. width: 8px;
  159. height: 33px;
  160. background: #ccc;
  161. border-radius: 0 0 0 8px;
  162. }
  163. }
  164. }
  165. &-add {
  166. height: 70%;
  167. margin-left: 5px;
  168. -webkit-app-region: no-drag;
  169. cursor: pointer;
  170. }
  171. }
  172. </style>