InformationSearchBar.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <view class="wrap">
  3. <view class="card">
  4. <!-- 左侧 region -->
  5. <view class="region" @tap="openPicker">
  6. <text class="region-text" :class="{ active: !!region }">
  7. {{ regionLabel }}
  8. </text>
  9. <wd-icon v-if="region" name="close" color="#8a94a6" class="clear" @tap.stop="clearRegion" />
  10. <wd-icon v-else name="down" color="#8a94a6" size="36rpx" class="clear"></wd-icon>
  11. </view>
  12. <!-- 分割 -->
  13. <view class="split" />
  14. <!-- 输入 -->
  15. <view class="input-box">
  16. <wd-search v-model="keyword" placeholder="请输入关键词" hide-cancel :show-action="false" />
  17. </view>
  18. </view>
  19. <!-- picker -->
  20. <wd-picker v-model:visible="visible" :columns="provinces" @confirm="onConfirm" />
  21. </view>
  22. </template>
  23. <script setup lang="ts">
  24. import { computed, ref, watch } from 'vue'
  25. import { debounce } from '@/plugins/debounce'
  26. import { provinces } from '@/constants/regionOptions'
  27. const emit = defineEmits<{
  28. search: [{ region: string; keyword: string }]
  29. }>()
  30. const region = ref('')
  31. const keyword = ref('')
  32. const visible = ref(false)
  33. const regionLabel = computed(() => {
  34. return region.value || '区域'
  35. })
  36. const openPicker = () => (visible.value = true)
  37. const clearRegion = () => {
  38. region.value = ''
  39. }
  40. interface PickerConfirmEvent {
  41. selectedItems: [
  42. {
  43. label: string
  44. value: string
  45. },
  46. ]
  47. value: string[]
  48. }
  49. const onConfirm = (value: PickerConfirmEvent) => {
  50. region.value = value.selectedItems[0].label
  51. }
  52. const doSearch = () => {
  53. emit('search', {
  54. region: region.value,
  55. keyword: keyword.value.trim(),
  56. })
  57. }
  58. const trigger = debounce(doSearch, 350)
  59. watch([region, keyword], trigger)
  60. </script>
  61. <style scoped lang="scss">
  62. .wrap {
  63. padding: 24rpx;
  64. }
  65. .card {
  66. display: flex;
  67. align-items: center;
  68. height: 92rpx;
  69. background: #ffffff;
  70. border-radius: 999rpx;
  71. box-shadow:
  72. 0 12rpx 30rpx rgba(0, 0, 0, 0.06),
  73. inset 0 0 0 1rpx rgba(0, 0, 0, 0.04);
  74. overflow: hidden;
  75. }
  76. /* region */
  77. .region {
  78. display: flex;
  79. align-items: center;
  80. padding: 0 22rpx;
  81. height: 100%;
  82. flex-shrink: 0;
  83. }
  84. .region-text {
  85. font-size: 28rpx;
  86. margin-right: 6rpx;
  87. color: #8a94a6;
  88. }
  89. .region-text.active {
  90. color: #1f2937;
  91. font-weight: 600;
  92. }
  93. .clear {
  94. margin-left: 10rpx;
  95. font-size: 22rpx;
  96. color: #9aa4b2;
  97. }
  98. /* split */
  99. .split {
  100. width: 1rpx;
  101. height: 42rpx;
  102. background: linear-gradient(#e5e7eb, #f3f4f6, #e5e7eb);
  103. }
  104. /* input */
  105. .input-box {
  106. flex: 1;
  107. padding-right: 16rpx;
  108. }
  109. /* 去掉 wd-search 默认背景 */
  110. :deep(.wd-search__block) {
  111. background: transparent !important;
  112. box-shadow: none !important;
  113. border: none !important;
  114. }
  115. :deep(.wd-search__input) {
  116. font-size: 30rpx;
  117. }
  118. </style>