GenerationPicker.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <view class="generation-picker-wrap">
  3. <view class="form-item required" v-if="showLabel">
  4. <text class="label"><text class="required-mark">*</text>辈分关系</text>
  5. </view>
  6. <picker :range="genLabels" @change="onGenerationChange" :disabled="disabled">
  7. <view class="picker" :class="{ 'picker-disabled': disabled }">
  8. <text>{{ selectedGenLabel || '请选择辈分' }}</text>
  9. </view>
  10. </picker>
  11. <!-- 同辈关系类型(仅当选中的是同辈时显示) -->
  12. <view class="peer-type-wrap" v-if="selectedGen === 'peer'">
  13. <view class="form-item">
  14. <text class="label"><text class="required-mark">*</text>同辈关系类型</text>
  15. </view>
  16. <view class="radio-group">
  17. <label class="radio-item" @tap="selectPeerType('sibling')">
  18. <view class="radio-icon" :class="{ active: selectedPeer === 'sibling' }">
  19. <view class="radio-inner" v-if="selectedPeer === 'sibling'"></view>
  20. </view>
  21. <text class="radio-label">兄弟姐妹</text>
  22. </label>
  23. <label class="radio-item" @tap="selectPeerType('spouse')">
  24. <view class="radio-icon" :class="{ active: selectedPeer === 'spouse' }">
  25. <view class="radio-inner" v-if="selectedPeer === 'spouse'"></view>
  26. </view>
  27. <text class="radio-label">配偶</text>
  28. </label>
  29. </view>
  30. </view>
  31. </view>
  32. </template>
  33. <script>
  34. import genLevel from '../utils/generationLevel.js'
  35. var GENERATION_LEVELS = genLevel.GENERATION_LEVELS
  36. var PEER_TYPES = genLevel.PEER_TYPES
  37. var getGenerationLabel = genLevel.getGenerationLabel
  38. var getPeerTypeLabel = genLevel.getPeerTypeLabel
  39. export default {
  40. name: 'GenerationPicker',
  41. props: {
  42. generationLevel: { type: String, default: '' },
  43. peerType: { type: String, default: '' },
  44. disabled: { type: Boolean, default: false },
  45. showLabel: { type: Boolean, default: true }
  46. },
  47. data() {
  48. return {
  49. GEN_LEVELS: GENERATION_LEVELS,
  50. selectedGen: this.generationLevel || '',
  51. selectedPeer: this.peerType || ''
  52. }
  53. },
  54. computed: {
  55. genLabels() {
  56. var labels = []
  57. for (var i = 0; i < this.GEN_LEVELS.length; i++) {
  58. labels.push(this.GEN_LEVELS[i].label)
  59. }
  60. return labels
  61. },
  62. selectedGenLabel() {
  63. return getGenerationLabel(this.selectedGen)
  64. }
  65. },
  66. watch: {
  67. generationLevel(val) {
  68. this.selectedGen = val || ''
  69. },
  70. peerType(val) {
  71. this.selectedPeer = val || ''
  72. }
  73. },
  74. methods: {
  75. onGenerationChange(e) {
  76. var idx = e.detail.value
  77. if (idx >= 0 && idx < this.GEN_LEVELS.length) {
  78. var gen = this.GEN_LEVELS[idx]
  79. this.selectedGen = gen.value
  80. if (gen.value !== 'peer') {
  81. this.selectedPeer = ''
  82. this.$emit('update:peerType', '')
  83. }
  84. this.$emit('update:generationLevel', this.selectedGen)
  85. }
  86. },
  87. selectPeerType(type) {
  88. this.selectedPeer = type
  89. this.$emit('update:peerType', type)
  90. }
  91. }
  92. }
  93. </script>
  94. <style scoped>
  95. .generation-picker-wrap {
  96. width: 100%;
  97. }
  98. .picker {
  99. border: 1rpx solid #ddd;
  100. border-radius: 10rpx;
  101. padding: 20rpx;
  102. font-size: 28rpx;
  103. color: #666;
  104. background: #fff;
  105. }
  106. .picker-disabled {
  107. background: #f5f5f5;
  108. color: #999;
  109. }
  110. .form-item {
  111. margin-bottom: 10rpx;
  112. }
  113. .form-item .label {
  114. display: block;
  115. font-size: 28rpx;
  116. color: #333;
  117. margin-bottom: 10rpx;
  118. font-weight: bold;
  119. }
  120. .required-mark {
  121. color: #F97316;
  122. margin-right: 4rpx;
  123. }
  124. .peer-type-wrap {
  125. margin-top: 20rpx;
  126. padding: 20rpx;
  127. background: #f9f9f9;
  128. border-radius: 10rpx;
  129. }
  130. .radio-group {
  131. display: flex;
  132. flex-direction: row;
  133. justify-content: space-around;
  134. }
  135. .radio-item {
  136. display: flex;
  137. flex-direction: row;
  138. align-items: center;
  139. }
  140. .radio-icon {
  141. width: 40rpx;
  142. height: 40rpx;
  143. border: 2rpx solid #ddd;
  144. border-radius: 50%;
  145. margin-right: 10rpx;
  146. display: flex;
  147. align-items: center;
  148. justify-content: center;
  149. }
  150. .radio-icon.active {
  151. border-color: #F97316;
  152. }
  153. .radio-inner {
  154. width: 20rpx;
  155. height: 20rpx;
  156. background: #F97316;
  157. border-radius: 50%;
  158. }
  159. .radio-label {
  160. font-size: 28rpx;
  161. color: #333;
  162. }
  163. </style>