cwg-asset-tabs.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <template>
  2. <view class="asset-tabs">
  3. <!-- PC/平板 标签栏 -->
  4. <view class="tab-list">
  5. <view
  6. v-for="tab in tabs"
  7. :key="tab.value"
  8. class="tab-item"
  9. :class="{ active: currentValue === tab.value }"
  10. @click="handleClick(tab.value)"
  11. >
  12. <text class="tab-label">{{ tab.text }}</text>
  13. </view>
  14. </view>
  15. <!-- 移动端 下拉选择器 -->
  16. <cwg-combox
  17. v-model:value="currentValue"
  18. :clearable="false"
  19. :options="tabs"
  20. :placeholder="t('placeholder.choose')"
  21. class="tab-picker"
  22. />
  23. </view>
  24. </template>
  25. <script setup>
  26. import { ref, watch } from 'vue'
  27. import { useI18n } from 'vue-i18n'
  28. const { t } = useI18n()
  29. // Props 定义
  30. const props = defineProps({
  31. tabs: {
  32. type: Array,
  33. required: true
  34. },
  35. // v-model 绑定的值
  36. modelValue: {
  37. type: [String, Number],
  38. required: true
  39. }
  40. })
  41. // Emits 定义
  42. const emit = defineEmits(['update:modelValue'])
  43. // 内部状态,同步 props.modelValue
  44. const currentValue = ref(props.modelValue)
  45. // 监听 props.modelValue 变化,更新内部状态
  46. watch(() => props.modelValue, (newVal) => {
  47. if (newVal !== currentValue.value) {
  48. currentValue.value = newVal
  49. }
  50. })
  51. // 监听内部状态变化,触发 update:modelValue 事件
  52. watch(currentValue, (newVal) => {
  53. emit('update:modelValue', newVal)
  54. })
  55. // 点击标签切换
  56. const handleClick = (value) => {
  57. if (value === currentValue.value) return
  58. currentValue.value = value
  59. }
  60. </script>
  61. <style lang="scss" scoped>
  62. @import "@/uni.scss";
  63. .asset-tabs {
  64. position: relative;
  65. width: 100%;
  66. margin-bottom: px2rpx(24);
  67. background-color: #fff;
  68. }
  69. .tab-list {
  70. display: flex;
  71. gap: px2rpx(20);
  72. margin: 0;
  73. padding: 0;
  74. border-bottom: 1px solid #e5e5e5;
  75. }
  76. .tab-item {
  77. text-align: center;
  78. cursor: pointer;
  79. padding: px2rpx(12) 0;
  80. }
  81. .tab-label {
  82. font-size: px2rpx(14);
  83. color: #666;
  84. transition: all 0.3s;
  85. }
  86. .tab-item.active .tab-label {
  87. color: var(--color-primary);
  88. font-weight: 500;
  89. border-bottom: 2px solid var(--color-primary);
  90. padding-bottom: px2rpx(10);
  91. }
  92. .tab-picker {
  93. display: none;
  94. width: 100%;
  95. box-sizing: border-box;
  96. }
  97. @media (max-width: 768px) {
  98. .tab-list {
  99. display: none;
  100. }
  101. .tab-picker {
  102. display: block;
  103. }
  104. }
  105. </style>