RadioBlock.vue 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <script setup name="RadioBlock">
  2. import { ref, onMounted } from "vue";
  3. const props = defineProps({
  4. col: Number,
  5. columns: {
  6. type: Array,
  7. default: () => [],
  8. },
  9. modelValue: {
  10. type: [String, Number],
  11. default: "",
  12. },
  13. name: {
  14. type: String,
  15. default: "",
  16. },
  17. });
  18. const selectIndex = ref(null);
  19. const emit = defineEmits(["change", "update:modelValue"]);
  20. onMounted(() => {
  21. if (props.modelValue) {
  22. selectIndex.value = props.modelValue;
  23. }
  24. });
  25. const onChange = (e) => {
  26. let value = +e.detail.value;
  27. if (Object.is(NaN, value)) {
  28. value = e.detail.value;
  29. }
  30. selectIndex.value = value;
  31. emit("update:modelValue", value);
  32. emit(
  33. "change",
  34. value,
  35. props.columns.find((item) => item.value === value)
  36. );
  37. };
  38. </script>
  39. <template>
  40. <radio-group :name="name" @change="onChange">
  41. <view
  42. class="grid"
  43. :style="{
  44. gridTemplateColumns: `repeat(${col || columns.length}, 1fr)`,
  45. }"
  46. >
  47. <label
  48. class="radio"
  49. :class="{
  50. active: selectIndex === item.value,
  51. }"
  52. v-for="item in columns"
  53. :key="item.value"
  54. >
  55. <radio
  56. class="uni-radio"
  57. :value="item.value"
  58. :checked="selectIndex === item.value"
  59. />
  60. <view @click="selectIndex = item.value">
  61. {{ item.label }}
  62. </view>
  63. </label>
  64. </view>
  65. </radio-group>
  66. </template>
  67. <style scoped lang="scss">
  68. @import "@/uni.scss";
  69. .grid {
  70. display: grid;
  71. gap: 22rpx;
  72. .radio {
  73. display: flex;
  74. align-items: center;
  75. justify-content: center;
  76. border: 1px solid #ccc;
  77. padding: 0 auto;
  78. font-weight: 500;
  79. font-size: 28rpx;
  80. color: #333333;
  81. border-radius: 8rpx;
  82. height: 60rpx;
  83. .uni-radio {
  84. width: 0;
  85. height: 0;
  86. opacity: 0;
  87. }
  88. }
  89. .radio.active {
  90. background-color: $primary;
  91. border-color: $primary;
  92. color: #fff;
  93. }
  94. }
  95. </style>