text-switch.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <!-- import textSwitch from "@/components/text-li-switch/text-li-switch.vue" -->
  2. <!-- <textSwitch v-model="prop.must" uncheck_text="非必选" checked_text="必选" @change="switchChange"></textSwitch> -->
  3. <!-- @change可以不写 -->
  4. <template>
  5. <view>
  6. <view class="switch_box row-b-c" :class="{ 'disabled-switch': disabled }"
  7. :style="{ backgroundColor: checked ? checkedbg : uncheckedbg, width: width + 'rpx', height: height + 'rpx', borderRadius: '100px' }"
  8. @click="changeSwitch">
  9. <view class="switch_text c-white" :class="checked ? ['to_left'] : ['_right', 'c-black']"
  10. :style="{ fontSize: size + 'rpx', 'padding-right': padding_right }">{{ checked ? checked_text :
  11. uncheck_text }}
  12. </view>
  13. <view class="round" :style="{
  14. left: checked ? '100%' : '2rpx',
  15. marginLeft: checked ? '-' + (Number(height) - 6) + 'rpx' : '', width: + height + 'rpx',
  16. height: + height - 10 + 'rpx',
  17. width: + height - 10 + 'rpx',
  18. borderRadius: height / 2 + 'rpx'
  19. }">
  20. </view>
  21. <!-- 禁用遮罩层 -->
  22. <view v-if="disabled" class="disabled-overlay"></view>
  23. </view>
  24. </view>
  25. </template>
  26. <script>
  27. export default {
  28. emits: ['click', 'change', 'update:modelValue', 'input'],
  29. model: {
  30. prop: 'modelValue',
  31. event: 'update:modelValue'
  32. },
  33. props: {
  34. modelValue: [String], // 修改为接收字符串值
  35. checkedbg: {
  36. type: String,
  37. default: '#626FF0'
  38. },
  39. uncheckedbg: {
  40. type: String,
  41. default: '#F67072'
  42. },
  43. width: {
  44. type: String,
  45. default: '130'
  46. },
  47. height: {
  48. type: String,
  49. default: '50'
  50. },
  51. uncheck_text: {
  52. type: String,
  53. default: ''
  54. },
  55. checked_text: {
  56. type: String,
  57. default: ''
  58. },
  59. size: {
  60. type: String,
  61. default: '24'
  62. },
  63. checked_value: {
  64. type: String,
  65. default: 'QUALIFIED'
  66. },
  67. uncheck_value: {
  68. type: String,
  69. default: 'UNQUALIFIED'
  70. },
  71. disabled: {
  72. type: Boolean,
  73. default: false
  74. }
  75. },
  76. data() {
  77. return {
  78. checked: false, // 修改为布尔值
  79. padding_right: '20rpx'
  80. }
  81. },
  82. created() {
  83. if (this.uncheck_text.length > this.checked_text.length) {
  84. this.padding_right = '10rpx'
  85. }
  86. // 根据传入的值初始化选中状态
  87. this.updateCheckedState();
  88. },
  89. watch: {
  90. modelValue: {
  91. handler(newVal) {
  92. this.updateCheckedState();
  93. },
  94. deep: true,
  95. immediate: true
  96. },
  97. checked_value: {
  98. handler() {
  99. this.updateCheckedState();
  100. },
  101. deep: true
  102. },
  103. uncheck_value: {
  104. handler() {
  105. this.updateCheckedState();
  106. },
  107. deep: true
  108. }
  109. },
  110. methods: {
  111. // 根据传入的值更新选中状态
  112. updateCheckedState() {
  113. if (this.modelValue === this.checked_value) {
  114. this.checked = true;
  115. } else if (this.modelValue === this.uncheck_value) {
  116. this.checked = false;
  117. }
  118. // 如果传入的值既不等于checked_value也不等于uncheck_value,保持当前状态
  119. },
  120. changeSwitch: function (e) {
  121. // 如果禁用状态,阻止切换
  122. if (this.disabled) {
  123. return;
  124. }
  125. this.checked = !this.checked;
  126. // 根据开关状态确定要传递的值
  127. const current_value = this.checked ? this.checked_value : this.uncheck_value;
  128. // TODO 兼容 vue2
  129. this.$emit('input', current_value);
  130. // TODO 兼容 vue3
  131. this.$emit('update:modelValue', current_value);
  132. this.$emit('change', current_value)
  133. }
  134. }
  135. }
  136. </script>
  137. <style>
  138. .row-c-c {
  139. display: flex;
  140. justify-content: center;
  141. align-items: center;
  142. }
  143. .c-white {
  144. color: #FFFFFF;
  145. }
  146. .c-black {
  147. color: #FFFFFF;
  148. }
  149. /* ---------- */
  150. .switch_box {
  151. position: relative;
  152. border: 1rpx solid #EEEEEE;
  153. background-color: #F6F6F6;
  154. transition: all 0.4s;
  155. display: flex;
  156. align-items: center;
  157. }
  158. .round {
  159. position: absolute;
  160. background-color: #FFFFFF;
  161. transition: all 0.4s;
  162. }
  163. .to_left {
  164. left: 0;
  165. margin-left: 0;
  166. }
  167. .to_right {
  168. left: 100%;
  169. margin-left: -50rpx;
  170. }
  171. .switch_text {
  172. position: absolute;
  173. padding: 0 20rpx;
  174. }
  175. ._right {
  176. right: 0;
  177. border-right: none !important;
  178. }
  179. /* 禁用状态样式 */
  180. .disabled-switch {
  181. pointer-events: none;
  182. user-select: none;
  183. opacity: 0.6;
  184. position: relative;
  185. }
  186. .disabled-overlay {
  187. position: absolute;
  188. top: 0;
  189. left: 0;
  190. right: 0;
  191. bottom: 0;
  192. background: rgba(128, 128, 128, 0.3);
  193. border-radius: 100px;
  194. z-index: 10;
  195. pointer-events: none;
  196. }
  197. </style>