cwg-currency-select.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <template>
  2. <u-action-sheet v-model:show="show" class="sheet">
  3. <view class="currency-mask">
  4. <view v-if="showSearch" class="search">
  5. <u-input v-model="inputValueDoc" class="form-input" type="text" :placeholder="placeholder" :clearable="true"
  6. autocomplete="off">
  7. <template #left-icon><cwg-icon name="cwg-search" :size="23" color="" />
  8. </template>
  9. </u-input>
  10. </view>
  11. <scroll-view class="currency-select" scroll-y="true">
  12. <view v-for="item in filteredOptions" :key="item.value" class="currency-item" @click="select(item)">
  13. <image :src="imageSrc(item.value)" alt="" srcset="" />
  14. {{ item.value }}
  15. <view class="text"> {{ item.text }} </view>
  16. </view>
  17. </scroll-view>
  18. </view>
  19. </u-action-sheet>
  20. </template>
  21. <script setup lang="ts">
  22. import { ref, computed, watch } from "vue";
  23. import { useI18n } from "vue-i18n";
  24. const props = defineProps<{
  25. modelValue: boolean;
  26. showSearch: boolean;
  27. placeholder: string;
  28. options: Array<{ text: string; value: string }>;
  29. }>();
  30. const emit = defineEmits(["update:modelValue", "select"]);
  31. const { t } = useI18n();
  32. const inputValueDoc = ref("");
  33. const show = ref(props.modelValue);
  34. const filteredOptions = computed(() => {
  35. if (!inputValueDoc.value) return props.options;
  36. const keyword = inputValueDoc.value.toLowerCase();
  37. return props.options.filter(
  38. (item) =>
  39. item.text.toLowerCase().includes(keyword) ||
  40. item.value.toLowerCase().includes(keyword)
  41. );
  42. });
  43. function imageSrc(currency: string) {
  44. const code = (currency || "").toString().toUpperCase();
  45. return `/static/images/currency/${code}.png`;
  46. }
  47. watch(
  48. () => props.modelValue,
  49. (val) => (show.value = val)
  50. );
  51. watch(show, (val) => emit("update:modelValue", val));
  52. function select(item: { text: string; value: string }) {
  53. emit("select", item);
  54. show.value = false;
  55. }
  56. </script>
  57. <style scoped lang="scss">
  58. @import "@/uni.scss";
  59. .currency-mask {
  60. padding: px2rpx(44) px2rpx(31) 0 px2rpx(31);
  61. }
  62. .search {
  63. color: #8e8a8a;
  64. font-family: Roboto;
  65. font-size: px2rpx(31);
  66. font-style: normal;
  67. font-weight: 400;
  68. line-height: px2rpx(44);
  69. letter-spacing: px2rpx(0.8);
  70. display: flex;
  71. justify-content: space-between;
  72. align-items: center;
  73. gap: px2rpx(82);
  74. :deep(.form-input) {
  75. padding: px2rpx(12) px2rpx(31) !important;
  76. border-radius: 30px;
  77. border: 1px solid #beb6b6;
  78. &::after {
  79. border: 0;
  80. }
  81. }
  82. :deep(.u-input__left-icon) {
  83. display: flex;
  84. align-items: center;
  85. }
  86. }
  87. .currency-select {
  88. height: calc(80vh - px2rpx(98));
  89. overflow-y: auto;
  90. padding: 0 0 px2rpx(22) 0;
  91. display: flex;
  92. flex-direction: column;
  93. align-items: center;
  94. z-index: 2;
  95. }
  96. .currency-item {
  97. display: flex;
  98. padding: px2rpx(24) 0;
  99. align-items: center;
  100. gap: px2rpx(8);
  101. align-self: stretch;
  102. border-radius: 10px;
  103. color: #0e0f0c;
  104. font-size: px2rpx(31);
  105. font-style: normal;
  106. font-weight: 400;
  107. line-height: px2rpx(44);
  108. letter-spacing: -px2rpx(0.8);
  109. .text {
  110. color: #454745;
  111. font-family: Inter;
  112. font-size: px2rpx(14);
  113. font-style: normal;
  114. font-weight: 400;
  115. line-height: px2rpx(22);
  116. letter-spacing: px2rpx(0.14);
  117. }
  118. image {
  119. display: flex;
  120. width: px2rpx(48);
  121. height: px2rpx(48);
  122. justify-content: center;
  123. align-items: center;
  124. aspect-ratio: 1/1;
  125. border-radius: 100px;
  126. border: 1px solid rgba(14, 15, 12, 0.12);
  127. }
  128. }
  129. </style>