uview-pro 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/changelog.md +6 -0
  2. package/components/u-action-sheet/u-action-sheet.vue +205 -0
  3. package/components/u-alert-tips/u-alert-tips.vue +241 -0
  4. package/components/u-avatar/u-avatar.vue +220 -0
  5. package/components/u-avatar-cropper/u-avatar-cropper.vue +329 -0
  6. package/components/u-avatar-cropper/weCropper.d.ts +54 -0
  7. package/components/u-avatar-cropper/weCropper.js +1267 -0
  8. package/components/u-avatar-cropper/weCropper.ts +1254 -0
  9. package/components/u-back-top/u-back-top.vue +156 -0
  10. package/components/u-badge/u-badge.vue +189 -0
  11. package/components/u-button/u-button.vue +562 -0
  12. package/components/u-calendar/u-calendar.vue +725 -0
  13. package/components/u-car-keyboard/u-car-keyboard.vue +236 -0
  14. package/components/u-card/u-card.vue +240 -0
  15. package/components/u-cell-group/u-cell-group.vue +56 -0
  16. package/components/u-cell-item/u-cell-item.vue +245 -0
  17. package/components/u-checkbox/u-checkbox.vue +310 -0
  18. package/components/u-checkbox-group/u-checkbox-group.vue +134 -0
  19. package/components/u-circle-progress/u-circle-progress.vue +210 -0
  20. package/components/u-col/u-col.vue +135 -0
  21. package/components/u-collapse/u-collapse.vue +82 -0
  22. package/components/u-collapse-item/u-collapse-item.vue +190 -0
  23. package/components/u-column-notice/u-column-notice.vue +264 -0
  24. package/components/u-count-down/u-count-down.vue +333 -0
  25. package/components/u-count-to/u-count-to.vue +297 -0
  26. package/components/u-divider/u-divider.vue +141 -0
  27. package/components/u-dropdown/u-dropdown.vue +311 -0
  28. package/components/u-dropdown-item/u-dropdown-item.vue +135 -0
  29. package/components/u-empty/u-empty.vue +111 -0
  30. package/components/u-field/u-field.vue +469 -0
  31. package/components/u-form/u-form.vue +162 -0
  32. package/components/u-form-item/u-form-item.vue +476 -0
  33. package/components/u-full-screen/u-full-screen.vue +80 -0
  34. package/components/u-gap/u-gap.vue +48 -0
  35. package/components/u-grid/u-grid.vue +101 -0
  36. package/components/u-grid-item/u-grid-item.vue +136 -0
  37. package/components/u-icon/u-icon.vue +389 -0
  38. package/components/u-image/types.ts +48 -0
  39. package/components/u-image/u-image.vue +218 -0
  40. package/components/u-index-anchor/u-index-anchor.vue +101 -0
  41. package/components/u-index-list/u-index-list.vue +376 -0
  42. package/components/u-input/u-input.vue +462 -0
  43. package/components/u-keyboard/u-keyboard.vue +188 -0
  44. package/components/u-lazy-load/u-lazy-load.vue +288 -0
  45. package/components/u-line/u-line.vue +71 -0
  46. package/components/u-line-progress/u-line-progress.vue +128 -0
  47. package/components/u-link/u-link.vue +87 -0
  48. package/components/u-loading/u-loading.vue +111 -0
  49. package/components/u-loadmore/u-loadmore.vue +205 -0
  50. package/components/u-mask/u-mask.vue +137 -0
  51. package/components/u-message-input/u-message-input.vue +315 -0
  52. package/components/u-modal/u-modal.vue +284 -0
  53. package/components/u-navbar/u-navbar.vue +314 -0
  54. package/components/u-no-network/image.ts +2 -0
  55. package/components/u-no-network/u-no-network.vue +311 -0
  56. package/components/u-notice-bar/u-notice-bar.vue +274 -0
  57. package/components/u-number-box/u-number-box.vue +344 -0
  58. package/components/u-number-keyboard/u-number-keyboard.vue +170 -0
  59. package/components/u-parse/libs/CssHandler.js +100 -0
  60. package/components/u-parse/libs/MpHtmlParser.js +580 -0
  61. package/components/u-parse/libs/config.js +80 -0
  62. package/components/u-parse/libs/handler.wxs +22 -0
  63. package/components/u-parse/libs/trees.vue +505 -0
  64. package/components/u-parse/u-parse.vue +645 -0
  65. package/components/u-picker/u-picker.vue +808 -0
  66. package/components/u-popup/u-popup.vue +404 -0
  67. package/components/u-radio/u-radio.vue +272 -0
  68. package/components/u-radio-group/u-radio-group.vue +116 -0
  69. package/components/u-rate/u-rate.vue +349 -0
  70. package/components/u-read-more/u-read-more.vue +199 -0
  71. package/components/u-row/u-row.vue +95 -0
  72. package/components/u-row-notice/u-row-notice.vue +273 -0
  73. package/components/u-search/u-search.vue +298 -0
  74. package/components/u-section/u-section.vue +175 -0
  75. package/components/u-select/u-select.vue +387 -0
  76. package/components/u-skeleton/u-skeleton.vue +230 -0
  77. package/components/u-slider/u-slider.vue +293 -0
  78. package/components/u-steps/u-steps.vue +200 -0
  79. package/components/u-sticky/u-sticky.vue +189 -0
  80. package/components/u-subsection/u-subsection.vue +388 -0
  81. package/components/u-swipe-action/u-swipe-action.vue +289 -0
  82. package/components/u-swiper/u-swiper.vue +305 -0
  83. package/components/u-switch/u-switch.vue +146 -0
  84. package/components/u-tabbar/u-tabbar.vue +347 -0
  85. package/components/u-table/u-table.vue +104 -0
  86. package/components/u-tabs/u-tabs.vue +322 -0
  87. package/components/u-tabs-swiper/u-tabs-swiper.vue +426 -0
  88. package/components/u-tag/u-tag.vue +270 -0
  89. package/components/u-td/u-td.vue +76 -0
  90. package/components/u-th/u-th.vue +70 -0
  91. package/components/u-time-line/u-time-line.vue +39 -0
  92. package/components/u-time-line-item/u-time-line-item.vue +88 -0
  93. package/components/u-toast/types.ts +4 -0
  94. package/components/u-toast/u-toast.vue +238 -0
  95. package/components/u-top-tips/u-top-tips.vue +118 -0
  96. package/components/u-tr/u-tr.vue +24 -0
  97. package/components/u-upload/u-upload.vue +600 -0
  98. package/components/u-verification-code/u-verification-code.vue +194 -0
  99. package/components/u-waterfall/u-waterfall.vue +186 -0
  100. package/iconfont.css +910 -0
  101. package/index.scss +23 -0
  102. package/index.ts +166 -0
  103. package/libs/config/config.ts +26 -0
  104. package/libs/config/zIndex.ts +37 -0
  105. package/libs/css/color.scss +155 -0
  106. package/libs/css/common.scss +176 -0
  107. package/libs/css/style.components.scss +7 -0
  108. package/libs/css/style.h5.scss +8 -0
  109. package/libs/css/style.mp.scss +72 -0
  110. package/libs/css/style.nvue.scss +3 -0
  111. package/libs/css/style.vue.scss +175 -0
  112. package/libs/function/$parent.ts +22 -0
  113. package/libs/function/addUnit.ts +13 -0
  114. package/libs/function/color.ts +37 -0
  115. package/libs/function/colorGradient.ts +123 -0
  116. package/libs/function/debounce.ts +28 -0
  117. package/libs/function/deepClone.ts +39 -0
  118. package/libs/function/deepMerge.ts +34 -0
  119. package/libs/function/getParent.ts +59 -0
  120. package/libs/function/getRect.ts +26 -0
  121. package/libs/function/guid.ts +42 -0
  122. package/libs/function/md5.ts +397 -0
  123. package/libs/function/parent.ts +21 -0
  124. package/libs/function/queryParams.ts +60 -0
  125. package/libs/function/random.ts +16 -0
  126. package/libs/function/randomArray.ts +11 -0
  127. package/libs/function/route.ts +118 -0
  128. package/libs/function/sys.ts +15 -0
  129. package/libs/function/test.ts +229 -0
  130. package/libs/function/throttle.ts +31 -0
  131. package/libs/function/timeFormat.ts +54 -0
  132. package/libs/function/timeFrom.ts +48 -0
  133. package/libs/function/toast.ts +14 -0
  134. package/libs/function/trim.ts +21 -0
  135. package/libs/function/type2icon.ts +36 -0
  136. package/libs/hooks/useEmitter.ts +77 -0
  137. package/libs/hooks/useParent.ts +29 -0
  138. package/libs/request/index.ts +237 -0
  139. package/libs/store/index.ts +88 -0
  140. package/libs/util/area.ts +1 -0
  141. package/libs/util/async-validator.js +1356 -0
  142. package/libs/util/city.ts +1 -0
  143. package/libs/util/emitter.ts +112 -0
  144. package/libs/util/mitt.ts +118 -0
  145. package/libs/util/parent.ts +20 -0
  146. package/libs/util/province.ts +1 -0
  147. package/package.json +98 -0
  148. package/readme.md +165 -0
  149. package/theme.scss +38 -0
@@ -0,0 +1,305 @@
1
+ <template>
2
+ <view class="u-swiper-wrap" :style="{ borderRadius: `${borderRadius}rpx` }">
3
+ <swiper
4
+ :current="elCurrent"
5
+ @change="change"
6
+ @animationfinish="animationfinish"
7
+ :interval="interval"
8
+ :circular="circular"
9
+ :duration="duration"
10
+ :autoplay="autoplay"
11
+ :previous-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'"
12
+ :next-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'"
13
+ :style="{ height: height + 'rpx', backgroundColor: bgColor }"
14
+ >
15
+ <swiper-item class="u-swiper-item" v-for="(item, index) in list" :key="index">
16
+ <view
17
+ class="u-list-image-wrap"
18
+ @tap.stop.prevent="listClick(index)"
19
+ :class="[uCurrent != index ? 'u-list-scale' : '']"
20
+ :style="{
21
+ borderRadius: `${borderRadius}rpx`,
22
+ transform: effect3d && uCurrent != index ? 'scaleY(0.9)' : 'scaleY(1)',
23
+ margin: effect3d && uCurrent != index ? '0 20rpx' : 0
24
+ }"
25
+ >
26
+ <image class="u-swiper-image" :src="item[name] || item" :mode="imgMode"></image>
27
+ <view v-if="title && item.title" class="u-swiper-title u-line-1" :style="[{ 'padding-bottom': titlePaddingBottom }, titleStyle]">
28
+ {{ item.title }}
29
+ </view>
30
+ </view>
31
+ </swiper-item>
32
+ </swiper>
33
+ <view
34
+ class="u-swiper-indicator"
35
+ :style="{
36
+ top: indicatorPos == 'topLeft' || indicatorPos == 'topCenter' || indicatorPos == 'topRight' ? '12rpx' : 'auto',
37
+ bottom: indicatorPos == 'bottomLeft' || indicatorPos == 'bottomCenter' || indicatorPos == 'bottomRight' ? '12rpx' : 'auto',
38
+ justifyContent: justifyContent,
39
+ padding: `0 ${effect3d ? '74rpx' : '24rpx'}`
40
+ }"
41
+ >
42
+ <block v-if="mode == 'rect'">
43
+ <view class="u-indicator-item-rect" :class="{ 'u-indicator-item-rect-active': index == uCurrent }" v-for="(item, index) in list" :key="index"></view>
44
+ </block>
45
+ <block v-if="mode == 'dot'">
46
+ <view class="u-indicator-item-dot" :class="{ 'u-indicator-item-dot-active': index == uCurrent }" v-for="(item, index) in list" :key="index"></view>
47
+ </block>
48
+ <block v-if="mode == 'round'">
49
+ <view class="u-indicator-item-round" :class="{ 'u-indicator-item-round-active': index == uCurrent }" v-for="(item, index) in list" :key="index"></view>
50
+ </block>
51
+ <block v-if="mode == 'number'">
52
+ <view class="u-indicator-item-number">{{ uCurrent + 1 }}/{{ list.length }}</view>
53
+ </block>
54
+ </view>
55
+ </view>
56
+ </template>
57
+
58
+ <script setup lang="ts">
59
+ import { ref, computed, watch } from 'vue';
60
+
61
+ defineOptions({ name: 'u-swiper' });
62
+ /**
63
+ * swiper 轮播图
64
+ * @description 该组件一般用于导航轮播,广告展示等场景,可开箱即用
65
+ * @tutorial https://www.uviewui.com/components/swiper.html
66
+ * @property {Array} list 轮播图数据,见官网"基本使用"说明
67
+ * @property {Boolean} title 是否显示标题文字,需要配合list参数,见官网说明(默认false)
68
+ * @property {String} mode 指示器模式,见官网说明(默认round)
69
+ * @property {String|Number} height 轮播图组件高度,单位rpx(默认250)
70
+ * @property {String} indicator-pos 指示器的位置(默认bottomCenter)
71
+ * @property {Boolean} effect3d 是否开启3D效果(默认false)
72
+ * @property {Boolean} autoplay 是否自动播放(默认true)
73
+ * @property {String|Number} interval 自动轮播时间间隔,单位ms(默认2500)
74
+ * @property {Boolean} circular 是否衔接播放,见官网说明(默认true)
75
+ * @property {String} bg-color 背景颜色(默认#f3f4f6)
76
+ * @property {String|Number} border-radius 轮播图圆角值,单位rpx(默认8)
77
+ * @property {Object} title-style 自定义标题样式
78
+ * @property {String|Number} effect3d-previous-margin mode = true模式的情况下,激活项与前后项之间的距离,单位rpx(默认50)
79
+ * @property {String} img-mode 图片的裁剪模式,详见image组件裁剪模式(默认aspectFill)
80
+ * @event {Function} click 点击轮播图时触发
81
+ * @example <u-swiper :list="list" mode="dot" indicator-pos="bottomRight"></u-swiper>
82
+ */
83
+
84
+ // props 定义,保留参数注释
85
+ const props = defineProps({
86
+ /** 轮播图的数据,格式如:[{image: 'xxxx', title: 'xxxx'},{image: 'yyyy', title: 'yyyy'}],其中title字段可选 */
87
+ list: { type: Array as () => Array<Record<string, any>>, default: () => [] },
88
+ /** 是否显示title标题 */
89
+ title: { type: Boolean, default: false },
90
+ /** 用户自定义的指示器的样式 */
91
+ indicator: { type: Object, default: () => ({}) },
92
+ /** 圆角值 */
93
+ borderRadius: { type: [Number, String], default: 8 },
94
+ /** 隔多久自动切换 */
95
+ interval: { type: [String, Number], default: 3000 },
96
+ /** 指示器的模式,rect|dot|number|round */
97
+ mode: { type: String, default: 'round' },
98
+ /** list的高度,单位rpx */
99
+ height: { type: [Number, String], default: 250 },
100
+ /** 指示器的位置,topLeft|topCenter|topRight|bottomLeft|bottomCenter|bottomRight */
101
+ indicatorPos: { type: String, default: 'bottomCenter' },
102
+ /** 是否开启缩放效果 */
103
+ effect3d: { type: Boolean, default: false },
104
+ /** 3D模式的情况下,激活item与前后item之间的距离,单位rpx */
105
+ effect3dPreviousMargin: { type: [Number, String], default: 50 },
106
+ /** 是否自动播放 */
107
+ autoplay: { type: Boolean, default: true },
108
+ /** 自动轮播时间间隔,单位ms */
109
+ duration: { type: [Number, String], default: 500 },
110
+ /** 是否衔接滑动,即到最后一张时接着滑动,是否自动切换到第一张 */
111
+ circular: { type: Boolean, default: true },
112
+ /** 图片的裁剪模式 */
113
+ imgMode: { type: String, default: 'aspectFill' },
114
+ /** 从list数组中读取的图片的属性名 */
115
+ name: { type: String, default: 'image' },
116
+ /** 背景颜色 */
117
+ bgColor: { type: String, default: '#f3f4f6' },
118
+ /** 初始化时,默认显示第几项 */
119
+ current: { type: [Number, String], default: 0 },
120
+ /** 标题的样式,对象形式 */
121
+ titleStyle: { type: Object, default: () => ({}) }
122
+ });
123
+
124
+ // emits 定义
125
+ const emit = defineEmits(['click', 'change']);
126
+
127
+ // 当前活跃的swiper-item的index
128
+ const uCurrent = ref(Number(props.current));
129
+
130
+ // 监听list变化,重置uCurrent值,避免溢出
131
+ watch(
132
+ () => props.list,
133
+ (nVal, oVal) => {
134
+ if (nVal.length !== oVal.length) uCurrent.value = 0;
135
+ }
136
+ );
137
+ // 监听外部current的变化,实时修改内部依赖于此测uCurrent值
138
+ watch(
139
+ () => props.current,
140
+ n => {
141
+ uCurrent.value = Number(n);
142
+ }
143
+ );
144
+
145
+ // 容器 justifyContent
146
+ const justifyContent = computed(() => {
147
+ if (props.indicatorPos == 'topLeft' || props.indicatorPos == 'bottomLeft') return 'flex-start';
148
+ if (props.indicatorPos == 'topCenter' || props.indicatorPos == 'bottomCenter') return 'center';
149
+ if (props.indicatorPos == 'topRight' || props.indicatorPos == 'bottomRight') return 'flex-end';
150
+ return 'center';
151
+ });
152
+
153
+ // 标题下边距
154
+ const titlePaddingBottom = computed(() => {
155
+ if (props.mode == 'none') return '12rpx';
156
+ if (['bottomLeft', 'bottomCenter', 'bottomRight'].includes(props.indicatorPos) && props.mode == 'number') {
157
+ return '60rpx';
158
+ } else if (['bottomLeft', 'bottomCenter', 'bottomRight'].includes(props.indicatorPos) && props.mode != 'number') {
159
+ return '40rpx';
160
+ } else {
161
+ return '12rpx';
162
+ }
163
+ });
164
+
165
+ // swiper组件current参数只接受Number类型
166
+ const elCurrent = computed(() => Number(props.current));
167
+
168
+ /**
169
+ * 点击轮播图项
170
+ */
171
+ function listClick(index: number) {
172
+ emit('click', index);
173
+ }
174
+
175
+ /**
176
+ * swiper change事件
177
+ */
178
+ function change(e: any) {
179
+ const current = e.detail.current;
180
+ uCurrent.value = current;
181
+ emit('change', current);
182
+ }
183
+
184
+ /**
185
+ * swiper animationfinish事件
186
+ * 头条小程序不支持animationfinish事件,改由change事件
187
+ * 暂不监听此事件,因为不再给swiper绑定uCurrent属性
188
+ */
189
+ function animationfinish(e: any) {
190
+ // #ifndef MP-TOUTIAO
191
+ // uCurrent.value = e.detail.current
192
+ // #endif
193
+ }
194
+
195
+ defineExpose({ listClick, change, animationfinish });
196
+ </script>
197
+
198
+ <style lang="scss" scoped>
199
+ @import '../../libs/css/style.components.scss';
200
+
201
+ .u-swiper-wrap {
202
+ position: relative;
203
+ overflow: hidden;
204
+ transform: translateY(0);
205
+ }
206
+
207
+ .u-swiper-image {
208
+ width: 100%;
209
+ will-change: transform;
210
+ height: 100%;
211
+ /* #ifndef APP-NVUE */
212
+ display: block;
213
+ /* #endif */
214
+ /* #ifdef H5 */
215
+ pointer-events: none;
216
+ /* #endif */
217
+ }
218
+
219
+ .u-swiper-indicator {
220
+ padding: 0 24rpx;
221
+ position: absolute;
222
+ @include vue-flex;
223
+ width: 100%;
224
+ z-index: 1;
225
+ }
226
+
227
+ .u-indicator-item-rect {
228
+ width: 26rpx;
229
+ height: 8rpx;
230
+ margin: 0 6rpx;
231
+ transition: all 0.5s;
232
+ background-color: rgba(0, 0, 0, 0.3);
233
+ }
234
+
235
+ .u-indicator-item-rect-active {
236
+ background-color: rgba(255, 255, 255, 0.8);
237
+ }
238
+
239
+ .u-indicator-item-dot {
240
+ width: 14rpx;
241
+ height: 14rpx;
242
+ margin: 0 6rpx;
243
+ border-radius: 20rpx;
244
+ transition: all 0.5s;
245
+ background-color: rgba(0, 0, 0, 0.3);
246
+ }
247
+
248
+ .u-indicator-item-dot-active {
249
+ background-color: rgba(255, 255, 255, 0.8);
250
+ }
251
+
252
+ .u-indicator-item-round {
253
+ width: 14rpx;
254
+ height: 14rpx;
255
+ margin: 0 6rpx;
256
+ border-radius: 20rpx;
257
+ transition: all 0.5s;
258
+ background-color: rgba(0, 0, 0, 0.3);
259
+ }
260
+
261
+ .u-indicator-item-round-active {
262
+ width: 34rpx;
263
+ background-color: rgba(255, 255, 255, 0.8);
264
+ }
265
+
266
+ .u-indicator-item-number {
267
+ padding: 6rpx 16rpx;
268
+ line-height: 1;
269
+ background-color: rgba(0, 0, 0, 0.3);
270
+ border-radius: 100rpx;
271
+ font-size: 26rpx;
272
+ color: rgba(255, 255, 255, 0.8);
273
+ }
274
+
275
+ .u-list-scale {
276
+ transform-origin: center center;
277
+ }
278
+
279
+ .u-list-image-wrap {
280
+ width: 100%;
281
+ height: 100%;
282
+ flex: 1;
283
+ transition: all 0.5s;
284
+ overflow: hidden;
285
+ box-sizing: content-box;
286
+ position: relative;
287
+ }
288
+
289
+ .u-swiper-title {
290
+ position: absolute;
291
+ background-color: rgba(0, 0, 0, 0.3);
292
+ bottom: 0;
293
+ left: 0;
294
+ width: 100%;
295
+ font-size: 28rpx;
296
+ padding: 12rpx 24rpx;
297
+ color: rgba(255, 255, 255, 0.9);
298
+ }
299
+
300
+ .u-swiper-item {
301
+ @include vue-flex;
302
+ overflow: hidden;
303
+ align-items: center;
304
+ }
305
+ </style>
@@ -0,0 +1,146 @@
1
+ <template>
2
+ <view class="u-switch" :class="[modelValue == true ? 'u-switch--on' : '', disabled ? 'u-switch--disabled' : '']" @tap="onClick" :style="[switchStyle]">
3
+ <view
4
+ class="u-switch__node node-class"
5
+ :style="{
6
+ width: $u.addUnit(size ?? 50),
7
+ height: $u.addUnit(size ?? 50)
8
+ }"
9
+ >
10
+ <u-loading :show="loading" class="u-switch__loading" :size="Number(size) * 0.6" :color="loadingColor" />
11
+ </view>
12
+ </view>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { computed, nextTick } from 'vue';
17
+ import { $u } from '../..';
18
+
19
+ defineOptions({
20
+ name: 'u-switch'
21
+ });
22
+
23
+ /**
24
+ * switch 开关选择器
25
+ * @description 选择开关一般用于只有两个选择,且只能选其一的场景。
26
+ * @tutorial https://www.uviewui.com/components/switch.html
27
+ * @property {Boolean} loading 是否处于加载中(默认false)
28
+ * @property {Boolean} disabled 是否禁用(默认false)
29
+ * @property {String|Number} size 开关尺寸,单位rpx(默认50)
30
+ * @property {String} active-color 打开时的背景色(默认#2979ff)
31
+ * @property {String} inactive-color 关闭时的背景色(默认#ffffff)
32
+ * @property {Boolean|Number|String} active-value 打开选择器时通过change事件发出的值(默认true)
33
+ * @property {Boolean|Number|String} inactive-value 关闭选择器时通过change事件发出的值(默认false)
34
+ * @event {Function} change 在switch打开或关闭时触发
35
+ * @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch>
36
+ */
37
+ const props = defineProps({
38
+ /** 是否为加载中状态 */
39
+ loading: { type: Boolean, default: false },
40
+ /** 是否为禁用状态 */
41
+ disabled: { type: Boolean, default: false },
42
+ /** 开关尺寸,单位rpx */
43
+ size: { type: [Number, String], default: 50 },
44
+ /** 打开时的背景颜色 */
45
+ activeColor: { type: String, default: '#2979ff' },
46
+ /** 关闭时的背景颜色 */
47
+ inactiveColor: { type: String, default: '#ffffff' },
48
+ /** 通过v-model双向绑定的值 */
49
+ modelValue: { type: Boolean, default: false },
50
+ /** 是否使手机发生短促震动,目前只在iOS的微信小程序有效(2020-05-06) */
51
+ vibrateShort: { type: Boolean, default: false },
52
+ /** 打开选择器时的值 */
53
+ activeValue: { type: [Number, String, Boolean], default: true },
54
+ /** 关闭选择器时的值 */
55
+ inactiveValue: { type: [Number, String, Boolean], default: false }
56
+ });
57
+
58
+ const emit = defineEmits(['update:modelValue', 'change']);
59
+
60
+ /**
61
+ * 计算开关样式
62
+ */
63
+ const switchStyle = computed(() => {
64
+ let style: Record<string, string> = {};
65
+ style.fontSize = props.size + 'rpx';
66
+ style.backgroundColor = props.modelValue ? props.activeColor : props.inactiveColor;
67
+ return style;
68
+ });
69
+ /**
70
+ * 计算加载动画颜色
71
+ */
72
+ const loadingColor = computed(() => {
73
+ return props.modelValue ? props.activeColor : null;
74
+ });
75
+
76
+ /**
77
+ * 点击开关
78
+ */
79
+ function onClick() {
80
+ if (!props.disabled && !props.loading) {
81
+ // 使手机产生短促震动,微信小程序有效,APP(HX 2.6.8)和H5无效
82
+ if (props.vibrateShort) uni.vibrateShort();
83
+ emit('update:modelValue', !props.modelValue);
84
+ // 放到下一个生命周期,因为双向绑定的value修改父组件状态需要时间,且是异步的
85
+ nextTick(() => {
86
+ emit('change', props.modelValue ? props.activeValue : props.inactiveValue);
87
+ });
88
+ }
89
+ }
90
+ </script>
91
+
92
+ <style lang="scss" scoped>
93
+ @import '../../libs/css/style.components.scss';
94
+
95
+ .u-switch {
96
+ position: relative;
97
+ /* #ifndef APP-NVUE */
98
+ display: inline-block;
99
+ /* #endif */
100
+ box-sizing: initial;
101
+ width: 2em;
102
+ height: 1em;
103
+ background-color: #fff;
104
+ border: 1px solid rgba(0, 0, 0, 0.1);
105
+ border-radius: 1em;
106
+ transition: background-color 0.3s;
107
+ font-size: 50rpx;
108
+ }
109
+
110
+ .u-switch__node {
111
+ @include vue-flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ position: absolute;
115
+ top: 0;
116
+ left: 0;
117
+ border-radius: 100%;
118
+ z-index: 1;
119
+ background-color: #fff;
120
+ background-color: #fff;
121
+ box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
122
+ box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
123
+ transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
124
+ transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05), -webkit-transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
125
+ transition: transform cubic-bezier(0.3, 1.05, 0.4, 1.05);
126
+ transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
127
+ }
128
+
129
+ .u-switch__loading {
130
+ @include vue-flex;
131
+ align-items: center;
132
+ justify-content: center;
133
+ }
134
+
135
+ .u-switch--on {
136
+ background-color: #1989fa;
137
+ }
138
+
139
+ .u-switch--on .u-switch__node {
140
+ transform: translateX(100%);
141
+ }
142
+
143
+ .u-switch--disabled {
144
+ opacity: 0.4;
145
+ }
146
+ </style>