picker.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template>
  2. <view class="iosBottom">
  3. <uni-popup ref="popupRef" type="bottom">
  4. <view class="popup_header">
  5. <trans class="cancel_btn" :_t="cancelText" @click="handleClose" />
  6. <trans class="confirm_btn" :_t="confirmText" @click="handleConfirm" />
  7. </view>
  8. <picker-view
  9. v-if="true"
  10. :indicator-style="indicatorStyle"
  11. :value="value"
  12. @change="handleChange"
  13. class="picker-view"
  14. mask-class="mask"
  15. >
  16. <picker-view-column>
  17. <view
  18. class="item"
  19. v-for="(item, index) in data"
  20. :key="`picker_${new Date().getTime}_${index}`"
  21. >
  22. <slot name="pickerItem" :item="item">
  23. {{ item[labelKey] }}
  24. </slot>
  25. </view>
  26. </picker-view-column>
  27. </picker-view>
  28. </uni-popup>
  29. </view>
  30. </template>
  31. <script setup>
  32. import { ref, computed } from "vue";
  33. const props = defineProps({
  34. data: {
  35. type: Array,
  36. default: () => [],
  37. },
  38. labelKey: {
  39. type: String,
  40. default: "label",
  41. },
  42. valueKey: {
  43. type: String,
  44. default: "value",
  45. },
  46. modelValue: {
  47. type: String,
  48. default: "",
  49. },
  50. cancelText: {
  51. type: String,
  52. default: "取消",
  53. },
  54. confirmText: {
  55. type: String,
  56. default: "确认",
  57. },
  58. });
  59. const emit = defineEmits(["update:modelValue", "confirm"]);
  60. const popupRef = ref(null);
  61. const value = ref(null);
  62. const indicatorStyle = `height: 50px;`;
  63. let tempObject = {};
  64. // methods
  65. function handleChange(e) {
  66. const index = e.detail.value[0];
  67. tempObject = props.data[index];
  68. }
  69. function handleClose() {
  70. tempObject = {};
  71. popupRef.value.close();
  72. }
  73. function setValue(val) {
  74. value.value = [val];
  75. // _setValue([val]);
  76. }
  77. function openPopup() {
  78. setValue(
  79. props.data.findIndex((item) => item[props.valueKey] === props.modelValue)
  80. );
  81. !!popupRef.value && popupRef.value.open();
  82. }
  83. function handleConfirm() {
  84. const item = props.data.find(
  85. (obj) => obj[props.valueKey] == props.modelValue
  86. );
  87. // if (tempObject[props.valueKey]) {
  88. emit("update:modelValue", tempObject[props.valueKey] || item[props.valueKey]);
  89. emit("confirm", JSON.stringify(tempObject) != "{}" ? tempObject : item);
  90. // }
  91. handleClose();
  92. }
  93. defineExpose({
  94. open: openPopup,
  95. });
  96. </script>
  97. <style lang="less" scoped>
  98. @import url("@/style.less");
  99. .picker-view {
  100. height: 500rpx;
  101. margin-top: 20rpx;
  102. }
  103. /deep/ .uni-picker-view-indicator {
  104. height: 68rpx !important;
  105. }
  106. /deep/ .uni-popup {
  107. z-index: 999999;
  108. }
  109. .item {
  110. height: 68rpx !important;
  111. line-height: 68rpx;
  112. text-align: center;
  113. color: var(--black);
  114. font-size: 24rpx;
  115. background: var(--bg);
  116. }
  117. .areacode_text {
  118. color: var(--light);
  119. }
  120. .popup_header {
  121. display: flex;
  122. align-items: center;
  123. justify-content: space-between;
  124. background-color: var(--light);
  125. height: 82rpx;
  126. // border-bottom: 1px solid var(--borderColor);
  127. .btn {
  128. line-height: 82rpx;
  129. padding: 0 40rpx;
  130. font-size: 24rpx;
  131. }
  132. .cancel_btn {
  133. .btn();
  134. color: var(--black);
  135. }
  136. .confirm_btn {
  137. .btn();
  138. // color: #2979ff;
  139. color: var(--black);
  140. }
  141. }
  142. /deep/ .picker-view {
  143. margin-top: 0;
  144. .uni-picker-view-content {
  145. background: var(--light);
  146. }
  147. }
  148. .mask {
  149. background: var(--picker-mask);
  150. // background: red;
  151. background-position: top, bottom;
  152. background-repeat: no-repeat;
  153. background-size: 100% 100%;
  154. }
  155. .picker-view {
  156. background-color: var(--light);
  157. }
  158. :deep(.uni-picker-view-indicator) {
  159. background-color: var(--light);
  160. opacity: 0.3;
  161. }
  162. </style>