TabSearch.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <div :class="{'box_tab':props.tabType == 'box','line_tab':props.tabType == 'line'}">
  3. <span
  4. v-for="item in props.tabList"
  5. :key="item.key"
  6. :class="{
  7. 'selected': activedId == item.key,
  8. 'un_selected': activedId !== item.key,
  9. 'prefix':item.prefix,
  10. 'disabled':disabled
  11. }"
  12. @click="disabled ? '' : HandleTabChange(item.key)"
  13. >
  14. <img v-if="item.prefix" :src="activedId==item.key ? item.prefixLight : item.prefix" alt="" class="prefix" />
  15. {{ item.label }}
  16. <span v-if="item.suffix || item.suffix === 0" class="suffix">{{item.suffix}}</span>
  17. </span>
  18. </div>
  19. </template>
  20. <script setup lang="ts">
  21. import { ref, watch} from 'vue';
  22. interface TabItem {
  23. label:String,
  24. key:String,
  25. prefix?:String,
  26. prefixLight?:String,
  27. suffix?:String,
  28. }
  29. type TabType = 'box'|'line'
  30. const props = defineProps({
  31. tabList:{
  32. required:true,
  33. type:Array<TabItem>
  34. },
  35. tabType:{
  36. required:true,
  37. type:String
  38. },
  39. defaultTabKey:{
  40. required:true,
  41. type:String
  42. },
  43. disabled:{
  44. type:Boolean,
  45. default:false
  46. }
  47. })
  48. const emit = defineEmits(['tabChange'])
  49. const activedId = ref(props.defaultTabKey)
  50. watch([()=>props.defaultTabKey,()=>props.tabList],([newVal,newValList])=>{
  51. activedId.value = newVal
  52. },{immediate:true,deep:true})
  53. const HandleTabChange = async (params) =>{
  54. activedId.value = params
  55. emit('tabChange',activedId.value)
  56. }
  57. </script>
  58. <style lang="scss" scoped>
  59. .box_tab {
  60. display: flex;
  61. flex-direction: row;
  62. flex-wrap: wrap;
  63. font-size: 14px;
  64. > span{
  65. height: 36px;
  66. display: flex;
  67. gap:4px;
  68. justify-content: center;
  69. align-items: center;
  70. line-height: 1.5 !important;
  71. padding:7px 12px;
  72. cursor: pointer;
  73. .prefix{
  74. width: 16px;
  75. height: 16px;
  76. }
  77. }
  78. .un_selected{
  79. border: 1px solid #dcdfe6;
  80. color: #666;
  81. }
  82. .selected{
  83. background: #2E64FA;
  84. color: #fff;
  85. + span{
  86. border-left: transparent;
  87. }
  88. &.prefix{
  89. background-color: rgba(46, 100, 250,0.1);
  90. color:rgba(46, 100, 250);
  91. border:solid #2E64FA 1px;
  92. }
  93. }
  94. > span:nth-child(1){
  95. border-radius: 4px 0 0 4px;
  96. }
  97. > span:last-child{
  98. border-radius:0 4px 4px 0;
  99. }
  100. >span:nth-child(n):not(:last-child):not(.selected){
  101. border-right: transparent;
  102. }
  103. }
  104. .line_tab{
  105. display: flex;
  106. gap:24px;
  107. padding-bottom: 10px;
  108. color:#666666;
  109. font-size:14px;
  110. >span{
  111. cursor: pointer;
  112. }
  113. .selected{
  114. position: relative;
  115. color: #2E64FA;
  116. font-weight: bold;
  117. &::after{
  118. position: absolute;
  119. left: 0;
  120. bottom: -10px;
  121. content:'';
  122. width: 100%;
  123. height: 2px;
  124. background-color: #2E64FA;
  125. }
  126. }
  127. }
  128. .box_tab,
  129. .line_tab{
  130. .disabled{
  131. cursor: not-allowed;
  132. }
  133. }
  134. </style>