index.vue 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. <template>
  2. <view v-if="modelValue" class="wrap" @click.stop="close">
  3. <view class="wrap-content" @click.stop>
  4. <wd-index-bar sticky>
  5. <view v-for="item in areaDataC" :key="item.index">
  6. <wd-index-anchor :index="item.index" />
  7. <wd-cell
  8. border
  9. clickable
  10. v-for="city in item.data"
  11. :key="city"
  12. :title="city"
  13. @click="handleClick(item.index, city)"
  14. ></wd-cell>
  15. </view>
  16. </wd-index-bar>
  17. </view>
  18. </view>
  19. </template>
  20. <script setup lang="ts">
  21. import { defineProps, defineEmits } from 'vue'
  22. // **定义类型**
  23. interface AreaItem {
  24. index: string
  25. data: string[]
  26. }
  27. // **定义 Props**
  28. const props = defineProps<{
  29. areaData: AreaItem[]
  30. modelValue: boolean
  31. }>()
  32. // **定义 Emit 事件**
  33. const emit = defineEmits(['update:modelValue', 'handleClick'])
  34. // **点击城市**
  35. const handleClick = (index: string, city: string) => {
  36. emit('handleClick', { index, city }) // 触发父组件事件
  37. emit('update:modelValue', false) // 关闭弹窗
  38. }
  39. const areaDataC = computed(() => props.areaData)
  40. // **点击背景关闭弹窗**
  41. const close = () => {
  42. emit('update:modelValue', false)
  43. }
  44. </script>
  45. <style lang="scss" scoped>
  46. .wrap {
  47. position: fixed;
  48. top: 0;
  49. left: 0;
  50. z-index: 9999;
  51. display: flex;
  52. align-items: flex-start;
  53. justify-content: center;
  54. width: 100vw;
  55. height: 100vh;
  56. background: rgba(0, 0, 0, 0.4);
  57. .wrap-content {
  58. position: relative;
  59. top: 176rpx;
  60. display: flex;
  61. flex-direction: column;
  62. width: 100%;
  63. height: calc(100vh - var(--window-top) - env(safe-area-inset-bottom));
  64. overflow: hidden;
  65. background: white;
  66. border-radius: 10px;
  67. }
  68. }
  69. </style>