muzhiyu-ui 1.0.0

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 (96) hide show
  1. package/README.md +202 -0
  2. package/components/muzhiyu/mu-action-sheet/mu-action-sheet.vue +335 -0
  3. package/components/muzhiyu/mu-alert/mu-alert.vue +220 -0
  4. package/components/muzhiyu/mu-back-top/mu-back-top.vue +161 -0
  5. package/components/muzhiyu/mu-badge/mu-badge.vue +150 -0
  6. package/components/muzhiyu/mu-barcode/mu-barcode.vue +100 -0
  7. package/components/muzhiyu/mu-blank/mu-blank.vue +30 -0
  8. package/components/muzhiyu/mu-bottom-nav/mu-bottom-nav.vue +331 -0
  9. package/components/muzhiyu/mu-bubble/mu-bubble.vue +316 -0
  10. package/components/muzhiyu/mu-button/mu-button.vue +431 -0
  11. package/components/muzhiyu/mu-calendar/mu-calendar.vue +429 -0
  12. package/components/muzhiyu/mu-car-input/mu-car-input.vue +209 -0
  13. package/components/muzhiyu/mu-card/mu-card.vue +317 -0
  14. package/components/muzhiyu/mu-cascader/mu-cascader.vue +336 -0
  15. package/components/muzhiyu/mu-cell/mu-cell.vue +368 -0
  16. package/components/muzhiyu/mu-checkbox/mu-checkbox.vue +116 -0
  17. package/components/muzhiyu/mu-checkbox-group/mu-checkbox-group.vue +40 -0
  18. package/components/muzhiyu/mu-code-input/mu-code-input.vue +264 -0
  19. package/components/muzhiyu/mu-collapse/mu-collapse.vue +316 -0
  20. package/components/muzhiyu/mu-color-picker/mu-color-picker.vue +466 -0
  21. package/components/muzhiyu/mu-config/index.js +34 -0
  22. package/components/muzhiyu/mu-config/mu-config.vue +54 -0
  23. package/components/muzhiyu/mu-countdown/mu-countdown.vue +338 -0
  24. package/components/muzhiyu/mu-cropper/mu-cropper.vue +415 -0
  25. package/components/muzhiyu/mu-date-picker/mu-date-picker.vue +290 -0
  26. package/components/muzhiyu/mu-datetime/mu-datetime.vue +262 -0
  27. package/components/muzhiyu/mu-divider/mu-divider.vue +229 -0
  28. package/components/muzhiyu/mu-drawer/mu-drawer.vue +172 -0
  29. package/components/muzhiyu/mu-dropdown/mu-dropdown.vue +215 -0
  30. package/components/muzhiyu/mu-dropdown-top/mu-dropdown-top.vue +243 -0
  31. package/components/muzhiyu/mu-empty/mu-empty.vue +217 -0
  32. package/components/muzhiyu/mu-fab/mu-fab.vue +324 -0
  33. package/components/muzhiyu/mu-footer/mu-footer.vue +21 -0
  34. package/components/muzhiyu/mu-form/mu-form.vue +170 -0
  35. package/components/muzhiyu/mu-grid/mu-grid.vue +95 -0
  36. package/components/muzhiyu/mu-grid-item/mu-grid-item.vue +247 -0
  37. package/components/muzhiyu/mu-html/mu-html.vue +145 -0
  38. package/components/muzhiyu/mu-icon/mu-icon.vue +822 -0
  39. package/components/muzhiyu/mu-image-grid/mu-image-grid.vue +225 -0
  40. package/components/muzhiyu/mu-image-preview/mu-image-preview.vue +286 -0
  41. package/components/muzhiyu/mu-index-list/mu-index-list.vue +381 -0
  42. package/components/muzhiyu/mu-input/mu-input.vue +570 -0
  43. package/components/muzhiyu/mu-input-number/mu-input-number.vue +193 -0
  44. package/components/muzhiyu/mu-keyboard/mu-keyboard.vue +415 -0
  45. package/components/muzhiyu/mu-list/mu-list.vue +89 -0
  46. package/components/muzhiyu/mu-loading/mu-loading.vue +124 -0
  47. package/components/muzhiyu/mu-loading-page/mu-loading-page.vue +529 -0
  48. package/components/muzhiyu/mu-loadmore/mu-loadmore.vue +26 -0
  49. package/components/muzhiyu/mu-modal/mu-modal.vue +298 -0
  50. package/components/muzhiyu/mu-navbar/mu-navbar.vue +223 -0
  51. package/components/muzhiyu/mu-nomore/mu-nomore.vue +107 -0
  52. package/components/muzhiyu/mu-notice-bar/mu-notice-bar.vue +284 -0
  53. package/components/muzhiyu/mu-notify/mu-notify.vue +202 -0
  54. package/components/muzhiyu/mu-overlay/mu-overlay.vue +94 -0
  55. package/components/muzhiyu/mu-pagination/mu-pagination.vue +330 -0
  56. package/components/muzhiyu/mu-password-input/mu-password-input.vue +119 -0
  57. package/components/muzhiyu/mu-picker/mu-picker.vue +297 -0
  58. package/components/muzhiyu/mu-popup/mu-popup.vue +297 -0
  59. package/components/muzhiyu/mu-progress/mu-progress.vue +156 -0
  60. package/components/muzhiyu/mu-pull-refresh/mu-pull-refresh.vue +54 -0
  61. package/components/muzhiyu/mu-qrcode/mu-qrcode.vue +340 -0
  62. package/components/muzhiyu/mu-qrcode/qrcode.js +2237 -0
  63. package/components/muzhiyu/mu-radio/mu-radio.vue +125 -0
  64. package/components/muzhiyu/mu-radio-group/mu-radio-group.vue +37 -0
  65. package/components/muzhiyu/mu-rate/mu-rate.vue +103 -0
  66. package/components/muzhiyu/mu-search/mu-search.vue +320 -0
  67. package/components/muzhiyu/mu-section/mu-section.vue +206 -0
  68. package/components/muzhiyu/mu-select/mu-select.vue +440 -0
  69. package/components/muzhiyu/mu-share-sheet/mu-share-sheet.vue +269 -0
  70. package/components/muzhiyu/mu-sidebar/mu-sidebar.vue +304 -0
  71. package/components/muzhiyu/mu-signature/mu-signature.vue +449 -0
  72. package/components/muzhiyu/mu-skeleton/mu-skeleton.vue +225 -0
  73. package/components/muzhiyu/mu-slider/mu-slider.vue +228 -0
  74. package/components/muzhiyu/mu-space/mu-space.vue +84 -0
  75. package/components/muzhiyu/mu-steps/mu-steps.vue +311 -0
  76. package/components/muzhiyu/mu-sticky/mu-sticky.vue +57 -0
  77. package/components/muzhiyu/mu-swipe-cell/mu-swipe-cell.vue +281 -0
  78. package/components/muzhiyu/mu-swiper/mu-swiper.vue +107 -0
  79. package/components/muzhiyu/mu-switch/mu-switch.vue +99 -0
  80. package/components/muzhiyu/mu-tabbar/mu-tabbar.vue +382 -0
  81. package/components/muzhiyu/mu-table/mu-table.vue +420 -0
  82. package/components/muzhiyu/mu-tabs/mu-tabs.vue +339 -0
  83. package/components/muzhiyu/mu-tag/mu-tag.vue +65 -0
  84. package/components/muzhiyu/mu-text-ellipsis/mu-text-ellipsis.vue +54 -0
  85. package/components/muzhiyu/mu-timeline/mu-timeline.vue +166 -0
  86. package/components/muzhiyu/mu-tips/mu-tips.vue +36 -0
  87. package/components/muzhiyu/mu-toast/mu-toast.vue +151 -0
  88. package/components/muzhiyu/mu-transfer/mu-transfer.vue +114 -0
  89. package/components/muzhiyu/mu-tree/mu-tree.vue +263 -0
  90. package/components/muzhiyu/mu-upload/mu-upload.vue +415 -0
  91. package/components/muzhiyu/mu-waterfall/mu-waterfall.vue +321 -0
  92. package/components/muzhiyu/mu-watermark/mu-watermark.vue +60 -0
  93. package/index.js +83 -0
  94. package/package.json +38 -0
  95. package/utils/index.js +600 -0
  96. package/utils/request.js +265 -0
@@ -0,0 +1,570 @@
1
+ <template>
2
+ <view class="mu-input" :class="[
3
+ `mu-input--${shape}`,
4
+ `mu-input--label-${computedLabelPosition}`,
5
+ type === 'textarea' && 'mu-input--textarea-type',
6
+ disabled && 'mu-input--disabled',
7
+ error && 'mu-input--error',
8
+ filled && 'mu-input--filled'
9
+ ]">
10
+ <!-- 标题 Label (包含必填红星与位置布局) -->
11
+ <view v-if="label || $slots.label" class="mu-input__label-box" :style="labelBoxStyle">
12
+ <text v-if="required" class="mu-input__required">*</text>
13
+ <slot name="label">
14
+ <text class="mu-input__label-text">{{ label }}</text>
15
+ </slot>
16
+ </view>
17
+
18
+ <!-- 输入框主容器 Main Box -->
19
+ <view class="mu-input__main">
20
+ <!-- 输入框围栏 Wrap -->
21
+ <view class="mu-input__wrap" @tap="handleWrapTap">
22
+ <!-- 前缀图标与插槽 -->
23
+ <view v-if="prefixIcon || $slots.prefix" class="mu-input__prefix">
24
+ <slot name="prefix">
25
+ <mu-icon :name="prefixIcon" :size="16" color="#94A3B8" />
26
+ </slot>
27
+ </view>
28
+
29
+ <!-- 手机号国家/地区固定前缀 (当 type === 'tel' 或 phonePrefix 开启时) -->
30
+ <view v-if="phonePrefix || type === 'tel'" class="mu-input__phone-prefix">
31
+ <text class="mu-input__phone-code">+86</text>
32
+ <view class="mu-input__phone-divider"></view>
33
+ </view>
34
+
35
+ <!-- Textarea 文本域 -->
36
+ <textarea v-if="type === 'textarea'" class="mu-input__textarea"
37
+ :value="innerValue" :placeholder="placeholder" :disabled="disabled" :maxlength="maxlength"
38
+ :auto-height="autoHeight" @input="onInput" @focus="onFocus" @blur="onBlur" />
39
+
40
+ <!-- 普通 / 数字 / 手机 / 密码 / 验证码 / 虚拟键盘 Input -->
41
+ <view v-else-if="isVirtualKeyboardActive" class="mu-input__virtual-box">
42
+ <text v-if="innerValue" class="mu-input__virtual-text">{{ innerValue }}</text>
43
+ <text v-else class="mu-input__virtual-placeholder">{{ placeholder }}</text>
44
+ <!-- 虚拟键盘激活时的打字闪烁光标 -->
45
+ <view v-if="showVirtualKeyboard" class="mu-input__cursor"></view>
46
+ </view>
47
+
48
+ <input v-else class="mu-input__inner"
49
+ :type="computedNativeType"
50
+ :value="innerValue"
51
+ :placeholder="placeholder"
52
+ :disabled="disabled"
53
+ :maxlength="computedMaxlength"
54
+ :password="isPasswordMasked"
55
+ @input="onInput"
56
+ @focus="onFocus"
57
+ @blur="onBlur"
58
+ />
59
+
60
+ <!-- 清除按钮 -->
61
+ <view v-if="clearable && innerValue" class="mu-input__clear" @tap.stop="onClear">
62
+ <mu-icon name="close" :size="12" color="#94A3B8" />
63
+ </view>
64
+
65
+ <!-- 密码显隐切换按钮 -->
66
+ <view v-if="type === 'password' || showPasswordToggle" class="mu-input__password-toggle" @tap.stop="togglePasswordVisible">
67
+ <mu-icon :name="showPassword ? 'eye' : 'eye_off'" :size="16" color="#94A3B8" />
68
+ </view>
69
+
70
+ <!-- 验证码发送倒计时微型小胶囊按键 -->
71
+ <view v-if="sendCode || type === 'code'" class="mu-input__code-btn-wrap">
72
+ <view class="mu-input__code-btn" :class="{ 'mu-input__code-btn--disabled': counting }" @tap.stop="handleSendCode">
73
+ <text class="mu-input__code-text">{{ counting ? `${seconds}s 后重试` : codeText }}</text>
74
+ </view>
75
+ </view>
76
+
77
+ <!-- 后缀图标与插槽 -->
78
+ <view v-if="suffixIcon || $slots.suffix" class="mu-input__suffix">
79
+ <slot name="suffix">
80
+ <mu-icon :name="suffixIcon" :size="16" color="#94A3B8" />
81
+ </slot>
82
+ </view>
83
+ </view>
84
+
85
+ <!-- 错误提示文本与计数器 -->
86
+ <text v-if="error" class="mu-input__error">{{ errorMessage }}</text>
87
+ <text v-if="counter && maxlength > 0" class="mu-input__counter">{{ (innerValue || '').length }}/{{ maxlength }}</text>
88
+ </view>
89
+
90
+ <!-- 联动自动弹出的虚拟键盘 -->
91
+ <mu-keyboard
92
+ v-if="isVirtualKeyboardActive"
93
+ v-model:show="showVirtualKeyboard"
94
+ v-model:value="innerValue"
95
+ :mode="computedKeyboardMode"
96
+ :title="keyboardTitle || label || '虚拟键盘'"
97
+ @change="onVirtualInputChange"
98
+ />
99
+ </view>
100
+ </template>
101
+
102
+ <script setup>
103
+ import { ref, watch, computed, inject, onUnmounted } from 'vue'
104
+
105
+ const muForm = inject('muForm', null) || inject('mu-form', null)
106
+
107
+ const props = defineProps({
108
+ modelValue: { type: [String, Number], default: '' },
109
+ type: { type: String, default: 'text' }, // text | number | digit | tel | password | code | textarea | car
110
+ shape: { type: String, default: 'radius' }, // square (微直角) | radius (圆角) | round (全圆胶囊)
111
+ filled: { type: Boolean, default: false }, // 是否背景纯底色填充模式
112
+ label: { type: String, default: '' },
113
+ labelPosition: { type: String, default: '' }, // top (独占顶置) | left (左侧同行同行)
114
+ labelWidth: { type: String, default: '' }, // 如 '160rpx'
115
+ required: { type: Boolean, default: false }, // 是否显示必填红星 *
116
+ placeholder: { type: String, default: '请输入' },
117
+ disabled: { type: Boolean, default: false },
118
+ clearable: { type: Boolean, default: false },
119
+ maxlength: { type: Number, default: -1 },
120
+ counter: { type: Boolean, default: false },
121
+ autoHeight: { type: Boolean, default: false },
122
+ error: { type: Boolean, default: false },
123
+ errorMessage: { type: String, default: '' },
124
+ prefixIcon: { type: String, default: '' },
125
+ suffixIcon: { type: String, default: '' },
126
+ phonePrefix: { type: Boolean, default: false },
127
+ showPasswordToggle: { type: Boolean, default: false },
128
+ sendCode: { type: Boolean, default: false },
129
+ codeText: { type: String, default: '获取验证码' },
130
+ codeSeconds: { type: Number, default: 60 },
131
+ useKeyboard: { type: Boolean, default: false }, // 是否启用关联弹出虚拟键盘
132
+ keyboardMode: { type: String, default: 'number' }, // number | idcard | car
133
+ keyboardTitle: { type: String, default: '' }
134
+ })
135
+
136
+ const emit = defineEmits(['update:modelValue', 'focus', 'blur', 'clear', 'input', 'send-code'])
137
+
138
+ // 计算继承自 mu-form 的 Label 布局
139
+ const computedLabelPosition = computed(() => {
140
+ if (props.labelPosition) return props.labelPosition
141
+ if (muForm && muForm.labelPosition) return muForm.labelPosition
142
+ return 'top'
143
+ })
144
+
145
+ const computedLabelWidth = computed(() => {
146
+ if (props.labelWidth) return props.labelWidth
147
+ if (muForm && muForm.labelWidth) return muForm.labelWidth
148
+ return '160rpx'
149
+ })
150
+
151
+ // 内部双向绑定代理
152
+ const innerValue = ref((props.modelValue !== undefined ? String(props.modelValue) : ''))
153
+ watch(() => props.modelValue, (val) => {
154
+ innerValue.value = (val !== undefined && val !== null ? String(val) : '')
155
+ })
156
+
157
+ const labelBoxStyle = computed(() => {
158
+ if (computedLabelPosition.value === 'left' && computedLabelWidth.value) {
159
+ return { width: computedLabelWidth.value }
160
+ }
161
+ return {}
162
+ })
163
+
164
+ // 虚拟键盘联动控制
165
+ const showVirtualKeyboard = ref(false)
166
+ const isVirtualKeyboardActive = computed(() => {
167
+ return props.useKeyboard || props.type === 'car'
168
+ })
169
+
170
+ const computedKeyboardMode = computed(() => {
171
+ if (props.type === 'car') return 'car'
172
+ return props.keyboardMode || 'number'
173
+ })
174
+
175
+ function handleWrapTap() {
176
+ if (props.disabled) return
177
+ if (isVirtualKeyboardActive.value) {
178
+ showVirtualKeyboard.value = true
179
+ emit('focus')
180
+ }
181
+ }
182
+
183
+ function onVirtualInputChange(val) {
184
+ innerValue.value = val
185
+ emit('update:modelValue', val)
186
+ emit('input', val)
187
+ }
188
+
189
+ // 密码显示隐藏控制
190
+ const showPassword = ref(false)
191
+ const isPasswordMasked = computed(() => {
192
+ if (props.type === 'password') {
193
+ return !showPassword.value
194
+ }
195
+ return false
196
+ })
197
+
198
+ function togglePasswordVisible() {
199
+ showPassword.value = !showPassword.value
200
+ }
201
+
202
+ // 原生键盘类型计算
203
+ const computedNativeType = computed(() => {
204
+ if (props.type === 'number' || props.type === 'tel' || props.type === 'code') {
205
+ return 'number'
206
+ }
207
+ if (props.type === 'digit') {
208
+ return 'digit'
209
+ }
210
+ return 'text'
211
+ })
212
+
213
+ // 最大长度计算
214
+ const computedMaxlength = computed(() => {
215
+ if (props.maxlength > 0) return props.maxlength
216
+ if (props.type === 'tel') return 11
217
+ if (props.type === 'code') return 6
218
+ if (props.type === 'car') return 8
219
+ return -1
220
+ })
221
+
222
+ // 验证码倒计时逻辑
223
+ const counting = ref(false)
224
+ const seconds = ref(props.codeSeconds)
225
+ let timer = null
226
+
227
+ function handleSendCode() {
228
+ if (counting.value || props.disabled) return
229
+ emit('send-code')
230
+ startCountdown()
231
+ }
232
+
233
+ function startCountdown() {
234
+ counting.value = true
235
+ seconds.value = props.codeSeconds
236
+ if (timer) clearInterval(timer)
237
+ timer = setInterval(() => {
238
+ seconds.value--
239
+ if (seconds.value <= 0) {
240
+ clearInterval(timer)
241
+ timer = null
242
+ counting.value = false
243
+ }
244
+ }, 1000)
245
+ }
246
+
247
+ function onInput(e) {
248
+ const val = e.detail.value
249
+ innerValue.value = val
250
+ emit('update:modelValue', val)
251
+ emit('input', val)
252
+ }
253
+
254
+ function onFocus(e) { emit('focus', e) }
255
+ function onBlur(e) { emit('blur', e) }
256
+ function onClear() {
257
+ innerValue.value = ''
258
+ emit('update:modelValue', '')
259
+ emit('clear')
260
+ }
261
+
262
+ onUnmounted(() => {
263
+ if (timer) clearInterval(timer)
264
+ })
265
+
266
+ defineExpose({
267
+ startCountdown
268
+ })
269
+ </script>
270
+
271
+ <style lang="scss" scoped>
272
+ @import "@/uni.scss";
273
+
274
+ .mu-input {
275
+ margin-bottom: 24rpx;
276
+
277
+ &--disabled { opacity: $mu-opacity-disabled; }
278
+ &--error {
279
+ .mu-input__wrap {
280
+ border-color: $mu-error;
281
+ box-shadow: 0 0 14rpx rgba(244, 63, 94, 0.2);
282
+ }
283
+ }
284
+
285
+ /* Label 布局配置 */
286
+ &--label-top {
287
+ display: flex;
288
+ flex-direction: column;
289
+ }
290
+
291
+ &--label-left {
292
+ display: flex;
293
+ align-items: center;
294
+ .mu-input__label-box {
295
+ margin-bottom: 0;
296
+ margin-right: 20rpx;
297
+ flex-shrink: 0;
298
+ width: 140rpx;
299
+ }
300
+ .mu-input__main {
301
+ flex: 1;
302
+ min-width: 0;
303
+ }
304
+ }
305
+
306
+ &--textarea-type#{&}--label-left {
307
+ align-items: flex-start;
308
+ .mu-input__label-box {
309
+ margin-top: 18rpx;
310
+ }
311
+ }
312
+
313
+ &__label-box {
314
+ display: flex;
315
+ align-items: center;
316
+ margin-bottom: 12rpx;
317
+ }
318
+
319
+ &__required {
320
+ color: #F43F5E;
321
+ font-size: 26rpx;
322
+ font-weight: 800;
323
+ margin-right: 6rpx;
324
+ line-height: 1;
325
+ }
326
+
327
+ &__label-text {
328
+ font-size: 26rpx;
329
+ color: $mu-text-primary;
330
+ font-weight: 700;
331
+ line-height: 1.4;
332
+ }
333
+
334
+ &__main {
335
+ width: 100%;
336
+ }
337
+
338
+ &__wrap {
339
+ display: flex;
340
+ align-items: center;
341
+ border: 1rpx solid $mu-border;
342
+ padding: 0 20rpx;
343
+ background: #ffffff;
344
+ transition: all $mu-duration $mu-ease;
345
+
346
+ &:focus-within {
347
+ border-color: $mu-primary;
348
+ box-shadow: 0 0 16rpx rgba(99, 102, 241, 0.2);
349
+ }
350
+ }
351
+
352
+ /* 虚拟键盘绑定文本框 */
353
+ &__virtual-box {
354
+ flex: 1;
355
+ height: 68rpx;
356
+ display: flex;
357
+ align-items: center;
358
+ position: relative;
359
+ }
360
+
361
+ &__virtual-text {
362
+ font-size: 26rpx;
363
+ color: $mu-text-primary;
364
+ font-weight: 600;
365
+ letter-spacing: 2rpx;
366
+ }
367
+
368
+ &__virtual-placeholder {
369
+ font-size: 26rpx;
370
+ color: #94A3B8;
371
+ }
372
+
373
+ &__cursor {
374
+ width: 3rpx;
375
+ height: 30rpx;
376
+ background: $mu-primary;
377
+ margin-left: 4rpx;
378
+ animation: mu-blink 1s infinite;
379
+ }
380
+
381
+ @keyframes mu-blink {
382
+ 0%, 100% { opacity: 1; }
383
+ 50% { opacity: 0; }
384
+ }
385
+
386
+ /* 多行文本域形态 (align-items 顶端对齐) */
387
+ &--textarea-type &__wrap {
388
+ align-items: flex-start;
389
+ padding: 12rpx 20rpx;
390
+ }
391
+
392
+ /* 填充背景模式 (:filled="true") */
393
+ &--filled &__wrap {
394
+ background: rgba(241, 245, 249, 0.6);
395
+ border-color: transparent;
396
+ }
397
+
398
+ /* 形态定义 (方形 / 柔和圆角 / 全圆胶囊) */
399
+ &--square &__wrap {
400
+ border-radius: 6rpx;
401
+ }
402
+ &--radius &__wrap {
403
+ border-radius: 12rpx;
404
+ }
405
+ &--round &__wrap {
406
+ border-radius: 999rpx;
407
+ padding: 0 28rpx;
408
+ }
409
+
410
+ &__inner {
411
+ flex: 1;
412
+ height: 68rpx;
413
+ font-size: 26rpx;
414
+ color: $mu-text-primary;
415
+ background: transparent;
416
+ border: none;
417
+ outline: none;
418
+ }
419
+
420
+ &__textarea {
421
+ flex: 1;
422
+ min-height: 140rpx;
423
+ font-size: 28rpx;
424
+ color: $mu-text-primary;
425
+ background: transparent;
426
+ border: none;
427
+ outline: none;
428
+ padding: 6rpx 0;
429
+ line-height: 1.5;
430
+ }
431
+
432
+ &__prefix {
433
+ margin-right: 16rpx;
434
+ display: flex;
435
+ align-items: center;
436
+ flex-shrink: 0;
437
+ margin-top: 4rpx;
438
+ }
439
+
440
+ &__suffix {
441
+ margin-left: 16rpx;
442
+ display: flex;
443
+ align-items: center;
444
+ flex-shrink: 0;
445
+ margin-top: 4rpx;
446
+ }
447
+
448
+ /* 手机号区号前缀 */
449
+ &__phone-prefix {
450
+ display: flex;
451
+ align-items: center;
452
+ margin-right: 16rpx;
453
+ flex-shrink: 0;
454
+ }
455
+
456
+ &__phone-code {
457
+ font-size: 28rpx;
458
+ font-weight: 700;
459
+ color: $mu-text-primary;
460
+ }
461
+
462
+ &__phone-divider {
463
+ width: 1rpx;
464
+ height: 24rpx;
465
+ background: $mu-border;
466
+ margin-left: 16rpx;
467
+ }
468
+
469
+ &__clear {
470
+ width: 32rpx;
471
+ height: 32rpx;
472
+ border-radius: 50%;
473
+ background: rgba(148, 163, 184, 0.15);
474
+ display: flex;
475
+ align-items: center;
476
+ justify-content: center;
477
+ cursor: pointer;
478
+ margin-left: 12rpx;
479
+ flex-shrink: 0;
480
+ }
481
+
482
+ &__password-toggle {
483
+ padding: 8rpx;
484
+ display: flex;
485
+ align-items: center;
486
+ justify-content: center;
487
+ cursor: pointer;
488
+ margin-left: 12rpx;
489
+ flex-shrink: 0;
490
+ }
491
+
492
+ /* 精致微型验证码胶囊按钮 */
493
+ &__code-btn-wrap {
494
+ margin-left: 12rpx;
495
+ flex-shrink: 0;
496
+ }
497
+
498
+ &__code-btn {
499
+ height: 48rpx;
500
+ padding: 0 18rpx;
501
+ display: inline-flex;
502
+ align-items: center;
503
+ justify-content: center;
504
+ border-radius: 24rpx;
505
+ background: rgba(99, 102, 241, 0.08);
506
+ border: 1rpx solid rgba(99, 102, 241, 0.18);
507
+ cursor: pointer;
508
+ transition: all 0.2s ease;
509
+
510
+ &--disabled {
511
+ background: rgba(148, 163, 184, 0.1);
512
+ border-color: transparent;
513
+ cursor: not-allowed;
514
+ .mu-input__code-text {
515
+ color: $mu-text-tertiary;
516
+ }
517
+ }
518
+ }
519
+
520
+ &__code-text {
521
+ font-size: 20rpx;
522
+ font-weight: 700;
523
+ color: $mu-primary;
524
+ line-height: 1;
525
+ }
526
+
527
+ &__error {
528
+ font-size: 22rpx;
529
+ color: $mu-error;
530
+ margin-top: 8rpx;
531
+ display: block;
532
+ }
533
+
534
+ &__counter {
535
+ font-size: 22rpx;
536
+ color: $mu-text-tertiary;
537
+ text-align: right;
538
+ margin-top: 8rpx;
539
+ display: block;
540
+ }
541
+ }
542
+
543
+ .mu-dark, page.mu-dark {
544
+
545
+ .mu-input {
546
+ &__label-text { color: $mu-dark-text-primary; }
547
+ &__wrap {
548
+ background: rgba(255, 255, 255, 0.04);
549
+ border-color: $mu-dark-border;
550
+ }
551
+ &__inner, &__textarea, &__virtual-text { color: $mu-dark-text-primary; }
552
+ &__phone-code { color: $mu-dark-text-primary; }
553
+ &__phone-divider { background: $mu-dark-border; }
554
+ }
555
+ }
556
+
557
+ @media (prefers-color-scheme: dark) {
558
+
559
+ .mu-input {
560
+ &__label-text { color: $mu-dark-text-primary; }
561
+ &__wrap {
562
+ background: rgba(255, 255, 255, 0.04);
563
+ border-color: $mu-dark-border;
564
+ }
565
+ &__inner, &__textarea, &__virtual-text { color: $mu-dark-text-primary; }
566
+ &__phone-code { color: $mu-dark-text-primary; }
567
+ &__phone-divider { background: $mu-dark-border; }
568
+ }
569
+ }
570
+ </style>