im-ui-mobile 0.1.0 → 0.1.2

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 (85) hide show
  1. package/components/im-avatar/im-avatar.vue +7 -7
  2. package/components/im-badge/im-badge.vue +326 -0
  3. package/components/im-button/im-button.vue +71 -34
  4. package/components/im-card/im-card.vue +563 -0
  5. package/components/im-chat-item/im-chat-item.vue +5 -4
  6. package/components/im-col/im-col.vue +191 -0
  7. package/components/im-dialog/im-dialog.vue +543 -0
  8. package/components/im-double-tap-view/im-double-tap-view.vue +93 -0
  9. package/components/im-emoji-picker/im-emoji-picker.vue +1143 -0
  10. package/components/im-friend-item/im-friend-item.vue +1 -1
  11. package/components/im-group-item/im-group-item.vue +1 -1
  12. package/components/im-group-member-selector/im-group-member-selector.vue +5 -5
  13. package/components/im-group-rtc-join/im-group-rtc-join.vue +8 -8
  14. package/components/im-icon/im-icon.vue +593 -0
  15. package/components/im-image-upload/im-image-upload.vue +0 -2
  16. package/components/im-link/im-link.vue +628 -0
  17. package/components/im-loading/im-loading.vue +13 -4
  18. package/components/im-mention-picker/im-mention-picker.vue +8 -7
  19. package/components/im-message-action/im-message-action.vue +678 -0
  20. package/components/im-message-item/im-message-item.vue +28 -26
  21. package/components/im-message-list/im-message-list.vue +1108 -0
  22. package/components/im-modal/im-modal.vue +373 -0
  23. package/components/im-nav-bar/im-nav-bar.vue +689 -75
  24. package/components/im-parse/im-parse.vue +1054 -0
  25. package/components/im-popup/im-popup.vue +467 -0
  26. package/components/im-read-receipt/im-read-receipt.vue +10 -10
  27. package/components/im-row/im-row.vue +189 -0
  28. package/components/im-search/im-search.vue +762 -0
  29. package/components/im-sku/im-sku.vue +720 -0
  30. package/components/im-sku/utils/helper.ts +182 -0
  31. package/components/im-stepper/im-stepper.vue +585 -0
  32. package/components/im-stepper/utils/helper.ts +167 -0
  33. package/components/im-tabs/im-tabs.vue +1022 -0
  34. package/components/im-tabs/tabs-navigation.vue +489 -0
  35. package/components/im-tabs/utils/helper.ts +181 -0
  36. package/components/im-tabs-tab-pane/im-tabs-tab-pane.vue +145 -0
  37. package/components/im-upload/im-upload.vue +1236 -0
  38. package/components/im-voice-input/im-voice-input.vue +1 -1
  39. package/index.js +3 -5
  40. package/index.scss +19 -0
  41. package/libs/emoji-data.ts +229 -0
  42. package/libs/index.ts +16 -16
  43. package/package.json +1 -2
  44. package/styles/button.scss +33 -33
  45. package/theme.scss +2 -2
  46. package/types/components/badge.d.ts +42 -0
  47. package/types/components/button.d.ts +2 -1
  48. package/types/components/card.d.ts +122 -0
  49. package/types/components/col.d.ts +37 -0
  50. package/types/components/dialog.d.ts +125 -0
  51. package/types/components/double-tap-view.d.ts +31 -0
  52. package/types/components/emoji-picker.d.ts +121 -0
  53. package/types/components/group-rtc-join.d.ts +1 -1
  54. package/types/components/icon.d.ts +77 -0
  55. package/types/components/link.d.ts +55 -0
  56. package/types/components/loading.d.ts +1 -0
  57. package/types/components/message-action.d.ts +96 -0
  58. package/types/components/message-item.d.ts +2 -2
  59. package/types/components/message-list.d.ts +136 -0
  60. package/types/components/modal.d.ts +106 -0
  61. package/types/components/nav-bar.d.ts +125 -0
  62. package/types/components/parse.d.ts +90 -0
  63. package/types/components/popup.d.ts +58 -0
  64. package/types/components/row.d.ts +31 -0
  65. package/types/components/search.d.ts +54 -0
  66. package/types/components/sku.d.ts +195 -0
  67. package/types/components/stepper.d.ts +99 -0
  68. package/types/components/tabs-tab-pane.d.ts +27 -0
  69. package/types/components/tabs.d.ts +117 -0
  70. package/types/components/upload.d.ts +137 -0
  71. package/types/components.d.ts +19 -1
  72. package/types/index.d.ts +38 -1
  73. package/types/libs/index.d.ts +10 -10
  74. package/types/utils/base64.d.ts +5 -0
  75. package/types/utils/dom.d.ts +3 -0
  76. package/types/utils/enums.d.ts +4 -5
  77. package/types/utils/validator.d.ts +74 -0
  78. package/utils/base64.js +18 -0
  79. package/utils/dom.js +353 -1
  80. package/utils/enums.js +4 -5
  81. package/utils/validator.js +230 -0
  82. package/components/im-file-upload/im-file-upload.vue +0 -309
  83. package/plugins/uview-plus.js +0 -29
  84. package/types/components/arrow-bar.d.ts +0 -14
  85. package/types/components/file-upload.d.ts +0 -58
@@ -0,0 +1,628 @@
1
+ <template>
2
+ <!-- 外部链接 -->
3
+ <view
4
+ v-if="isExternal"
5
+ class="im-link"
6
+ :class="[
7
+ `im-link--${type}`,
8
+ `im-link--${size}`,
9
+ `im-link--${underline}`,
10
+ { 'im-link--disabled': disabled },
11
+ { 'im-link--loading': loading },
12
+ customClass
13
+ ]"
14
+ :style="[customStyle, linkStyle]"
15
+ @tap="handleExternalLink"
16
+ >
17
+ <!-- 加载状态 -->
18
+ <view v-if="loading" class="im-link__loading">
19
+ <slot name="loading">
20
+ <view class="im-link__loading-icon"></view>
21
+ </slot>
22
+ </view>
23
+
24
+ <!-- 前置图标 -->
25
+ <view v-if="icon || $slots.icon" class="im-link__icon">
26
+ <slot name="icon">
27
+ <text v-if="icon" class="im-link__icon-text">{{ icon }}</text>
28
+ </slot>
29
+ </view>
30
+
31
+ <!-- 链接内容 -->
32
+ <text class="im-link__text">{{ text || href }}</text>
33
+
34
+ <!-- 后置图标 -->
35
+ <view v-if="showArrow || $slots.arrow" class="im-link__arrow">
36
+ <slot name="arrow">
37
+ <text v-if="showArrow" class="im-link__arrow-text">→</text>
38
+ </slot>
39
+ </view>
40
+
41
+ <!-- 角标 -->
42
+ <im-badge
43
+ v-if="badge"
44
+ class="im-link__badge"
45
+ :type="badgeType"
46
+ :value="badgeValue"
47
+ :max="badgeMax"
48
+ :dot="badgeDot"
49
+ :position="badgePosition"
50
+ />
51
+ </view>
52
+
53
+ <!-- 内部链接 -->
54
+ <navigator
55
+ v-else
56
+ class="im-link"
57
+ :class="[
58
+ `im-link--${type}`,
59
+ `im-link--${size}`,
60
+ `im-link--${underline}`,
61
+ { 'im-link--disabled': disabled },
62
+ { 'im-link--loading': loading },
63
+ customClass
64
+ ]"
65
+ :style="[customStyle, linkStyle]"
66
+ :url="href"
67
+ :open-type="openType"
68
+ :delta="delta"
69
+ :hover-class="hoverClass"
70
+ :hover-start-time="hoverStartTime"
71
+ :hover-stay-time="hoverStayTime"
72
+ @click="handleClick"
73
+ @success="handleSuccess"
74
+ @fail="handleFail"
75
+ @complete="handleComplete"
76
+ >
77
+ <!-- 加载状态 -->
78
+ <view v-if="loading" class="im-link__loading">
79
+ <slot name="loading">
80
+ <view class="im-link__loading-icon"></view>
81
+ </slot>
82
+ </view>
83
+
84
+ <!-- 前置图标 -->
85
+ <view v-if="icon || $slots.icon" class="im-link__icon">
86
+ <slot name="icon">
87
+ <text v-if="icon" class="im-link__icon-text">{{ icon }}</text>
88
+ </slot>
89
+ </view>
90
+
91
+ <!-- 链接内容 -->
92
+ <text class="im-link__text">{{ text }}</text>
93
+
94
+ <!-- 后置图标 -->
95
+ <view v-if="showArrow || $slots.arrow" class="im-link__arrow">
96
+ <slot name="arrow">
97
+ <text v-if="showArrow" class="im-link__arrow-text">→</text>
98
+ </slot>
99
+ </view>
100
+
101
+ <!-- 角标 -->
102
+ <im-badge
103
+ v-if="badge"
104
+ class="im-link__badge"
105
+ :type="badgeType"
106
+ :value="badgeValue"
107
+ :max="badgeMax"
108
+ :dot="badgeDot"
109
+ :position="badgePosition"
110
+ />
111
+ </navigator>
112
+ </template>
113
+
114
+ <script setup lang="ts">
115
+ import { computed } from 'vue'
116
+
117
+ // 定义 Props
118
+ interface Props {
119
+ // 链接配置
120
+ href?: string
121
+ text?: string
122
+ target?: '_self' | '_blank' | '_parent' | '_top'
123
+ rel?: string
124
+ download?: boolean
125
+
126
+ // 导航配置
127
+ openType?: 'navigate' | 'redirect' | 'switchTab' | 'reLaunch' | 'navigateBack'
128
+ delta?: number
129
+ hoverClass?: string
130
+ hoverStartTime?: number
131
+ hoverStayTime?: number
132
+
133
+ // 样式配置
134
+ type?: 'default' | 'primary' | 'success' | 'warning' | 'error' | 'info'
135
+ size?: 'small' | 'medium' | 'large'
136
+ underline?: 'none' | 'hover' | 'always'
137
+ disabled?: boolean
138
+ loading?: boolean
139
+
140
+ // 图标配置
141
+ icon?: string
142
+ showArrow?: boolean
143
+
144
+ // 角标配置
145
+ badge?: boolean
146
+ badgeType?: 'primary' | 'success' | 'warning' | 'danger' | 'info' //'primary' | 'success' | 'warning' | 'error' | 'info'
147
+ badgeValue?: string | number
148
+ badgeMax?: number
149
+ badgeDot?: boolean
150
+ badgePosition?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'
151
+
152
+ // 自定义样式
153
+ customClass?: string
154
+ customStyle?: string | Record<string, string>
155
+ color?: string
156
+ hoverColor?: string
157
+ activeColor?: string
158
+ fontSize?: string | number
159
+
160
+ // 事件配置
161
+ beforeNavigate?: (url: string) => boolean | Promise<boolean>
162
+ }
163
+
164
+ // 定义 Emits
165
+ interface Emits {
166
+ (e: 'click', event: any): void
167
+ (e: 'success', event: any): void
168
+ (e: 'fail', event: any): void
169
+ (e: 'complete', event: any): void
170
+ (e: 'before-navigate', url: string): void
171
+ (e: 'after-navigate', url: string): void
172
+ (e: 'navigate-error', error: Error): void
173
+ }
174
+
175
+ // 定义 Props 默认值
176
+ const props = withDefaults(defineProps<Props>(), {
177
+ href: '',
178
+ text: '',
179
+ target: '_self',
180
+ rel: 'noopener noreferrer',
181
+ download: false,
182
+
183
+ openType: 'navigate',
184
+ delta: 1,
185
+ hoverClass: 'im-link--hover',
186
+ hoverStartTime: 50,
187
+ hoverStayTime: 400,
188
+
189
+ type: 'primary',
190
+ size: 'medium',
191
+ underline: 'hover',
192
+ disabled: false,
193
+ loading: false,
194
+
195
+ icon: '',
196
+ showArrow: false,
197
+
198
+ badge: false,
199
+ badgeType: 'danger',
200
+ badgeValue: '',
201
+ badgeMax: 99,
202
+ badgeDot: false,
203
+ badgePosition: 'top-right',
204
+
205
+ customClass: '',
206
+ customStyle: () => ({}),
207
+ color: '',
208
+ hoverColor: '',
209
+ activeColor: '',
210
+ fontSize: '',
211
+
212
+ beforeNavigate: () => true
213
+ })
214
+
215
+ const emit = defineEmits<Emits>()
216
+
217
+ // 判断是否为外部链接
218
+ const isExternal = computed(() => {
219
+ if (!props.href) return false
220
+
221
+ return (
222
+ props.href.startsWith('http://') ||
223
+ props.href.startsWith('https://') ||
224
+ props.href.startsWith('//') ||
225
+ props.href.startsWith('mailto:') ||
226
+ props.href.startsWith('tel:')
227
+ )
228
+ })
229
+
230
+ // 链接样式
231
+ const linkStyle = computed(() => {
232
+ const style: Record<string, string> = {}
233
+
234
+ // 自定义颜色
235
+ if (props.color) {
236
+ style.color = props.color
237
+ }
238
+
239
+ // 字体大小
240
+ if (props.fontSize) {
241
+ const fontSize = typeof props.fontSize === 'number' ? `${props.fontSize}rpx` : props.fontSize
242
+ style.fontSize = fontSize
243
+ }
244
+
245
+ // 禁用状态
246
+ if (props.disabled) {
247
+ style.opacity = '0.6'
248
+ style.cursor = 'not-allowed'
249
+ }
250
+
251
+ // 加载状态
252
+ if (props.loading) {
253
+ style.opacity = '0.8'
254
+ }
255
+
256
+ return style
257
+ })
258
+
259
+ // 处理点击事件
260
+ const handleClick = async (event: any) => {
261
+ if (props.disabled || props.loading) {
262
+ return
263
+ }
264
+
265
+ emit('click', event)
266
+
267
+ // 执行前置导航钩子
268
+ if (props.beforeNavigate) {
269
+ try {
270
+ const shouldNavigate = await Promise.resolve(props.beforeNavigate(props.href))
271
+ if (!shouldNavigate) {
272
+ return
273
+ }
274
+ } catch (error) {
275
+ console.error('beforeNavigate error:', error)
276
+ return
277
+ }
278
+ }
279
+
280
+ emit('before-navigate', props.href)
281
+
282
+ // 如果是外部链接,已经在 handleExternalLink 中处理
283
+ if (!isExternal.value) {
284
+ // 内部链接由 navigator 组件处理
285
+ }
286
+ }
287
+
288
+ // 处理外部链接点击
289
+ const handleExternalLink = async (event: any) => {
290
+ if (props.disabled || props.loading) {
291
+ return
292
+ }
293
+
294
+ emit('click', event)
295
+
296
+ // 执行前置导航钩子
297
+ if (props.beforeNavigate) {
298
+ try {
299
+ const shouldNavigate = await Promise.resolve(props.beforeNavigate(props.href))
300
+ if (!shouldNavigate) {
301
+ return
302
+ }
303
+ } catch (error) {
304
+ console.error('beforeNavigate error:', error)
305
+ return
306
+ }
307
+ }
308
+
309
+ emit('before-navigate', props.href)
310
+
311
+ try {
312
+ // 处理不同类型的链接
313
+ if (props.href.startsWith('mailto:')) {
314
+ // 邮箱链接
315
+ window.location.href = props.href
316
+ } else if (props.href.startsWith('tel:')) {
317
+ // 电话链接
318
+ window.location.href = props.href
319
+ } else if (props.download) {
320
+ // 下载链接
321
+ window.open(props.href, props.target, `rel=${props.rel}`)
322
+ } else {
323
+ // 普通外部链接
324
+ if (props.target === '_blank') {
325
+ window.open(props.href, '_blank', `rel=${props.rel}`)
326
+ } else {
327
+ window.location.href = props.href
328
+ }
329
+ }
330
+
331
+ emit('after-navigate', props.href)
332
+ } catch (error) {
333
+ console.error('打开链接失败:', error)
334
+ emit('navigate-error', error as Error)
335
+ }
336
+ }
337
+
338
+ // 处理成功事件
339
+ const handleSuccess = (event: any) => {
340
+ emit('success', event)
341
+ }
342
+
343
+ // 处理失败事件
344
+ const handleFail = (event: any) => {
345
+ emit('fail', event)
346
+ }
347
+
348
+ // 处理完成事件
349
+ const handleComplete = (event: any) => {
350
+ emit('complete', event)
351
+ }
352
+
353
+ // 导航到指定页面
354
+ const navigateTo = (options: {
355
+ url: string
356
+ openType?: 'navigate' |'navigateBack'| 'redirect' | 'switchTab' | 'reLaunch'
357
+ delta?: number
358
+ }) => {
359
+ if (props.disabled || props.loading) {
360
+ return false
361
+ }
362
+
363
+ const { url, openType = 'navigate', delta = 1 } = options
364
+
365
+ try {
366
+ switch (openType) {
367
+ case 'navigate':
368
+ uni.navigateTo({ url })
369
+ break
370
+ case 'redirect':
371
+ uni.redirectTo({ url })
372
+ break
373
+ case 'switchTab':
374
+ uni.switchTab({ url })
375
+ break
376
+ case 'reLaunch':
377
+ uni.reLaunch({ url })
378
+ break
379
+ case 'navigateBack':
380
+ uni.navigateBack({ delta })
381
+ break
382
+ }
383
+ return true
384
+ } catch (error) {
385
+ console.error('导航失败:', error)
386
+ return false
387
+ }
388
+ }
389
+
390
+ // 暴露方法
391
+ defineExpose({
392
+ navigateTo
393
+ })
394
+ </script>
395
+
396
+ <style lang="scss" scoped>
397
+ .im-link {
398
+ display: inline-flex;
399
+ align-items: center;
400
+ cursor: pointer;
401
+ transition: all 0.3s ease;
402
+ position: relative;
403
+ text-decoration: none;
404
+ user-select: none;
405
+
406
+ // 尺寸
407
+ &--small {
408
+ padding: 8rpx 16rpx;
409
+ font-size: 24rpx;
410
+
411
+ .im-link__icon {
412
+ margin-right: 8rpx;
413
+ }
414
+
415
+ .im-link__arrow {
416
+ margin-left: 8rpx;
417
+ }
418
+ }
419
+
420
+ &--medium {
421
+ padding: 12rpx 24rpx;
422
+ font-size: 28rpx;
423
+
424
+ .im-link__icon {
425
+ margin-right: 12rpx;
426
+ }
427
+
428
+ .im-link__arrow {
429
+ margin-left: 12rpx;
430
+ }
431
+ }
432
+
433
+ &--large {
434
+ padding: 16rpx 32rpx;
435
+ font-size: 32rpx;
436
+
437
+ .im-link__icon {
438
+ margin-right: 16rpx;
439
+ }
440
+
441
+ .im-link__arrow {
442
+ margin-left: 16rpx;
443
+ }
444
+ }
445
+
446
+ // 类型
447
+ &--default {
448
+ color: #606266;
449
+
450
+ &:not(.im-link--disabled):not(.im-link--loading) {
451
+ &:hover {
452
+ color: #409eff;
453
+ }
454
+
455
+ &:active {
456
+ color: #337ecc;
457
+ }
458
+ }
459
+ }
460
+
461
+ &--primary {
462
+ color: #409eff;
463
+
464
+ &:not(.im-link--disabled):not(.im-link--loading) {
465
+ &:hover {
466
+ color: #66b1ff;
467
+ }
468
+
469
+ &:active {
470
+ color: #337ecc;
471
+ }
472
+ }
473
+ }
474
+
475
+ &--success {
476
+ color: #67c23a;
477
+
478
+ &:not(.im-link--disabled):not(.im-link--loading) {
479
+ &:hover {
480
+ color: #85ce61;
481
+ }
482
+
483
+ &:active {
484
+ color: #529b2d;
485
+ }
486
+ }
487
+ }
488
+
489
+ &--warning {
490
+ color: #e6a23c;
491
+
492
+ &:not(.im-link--disabled):not(.im-link--loading) {
493
+ &:hover {
494
+ color: #ebb563;
495
+ }
496
+
497
+ &:active {
498
+ color: #b88230;
499
+ }
500
+ }
501
+ }
502
+
503
+ &--error {
504
+ color: #f56c6c;
505
+
506
+ &:not(.im-link--disabled):not(.im-link--loading) {
507
+ &:hover {
508
+ color: #f78989;
509
+ }
510
+
511
+ &:active {
512
+ color: #c45656;
513
+ }
514
+ }
515
+ }
516
+
517
+ &--info {
518
+ color: #909399;
519
+
520
+ &:not(.im-link--disabled):not(.im-link--loading) {
521
+ &:hover {
522
+ color: #a6a9ad;
523
+ }
524
+
525
+ &:active {
526
+ color: #73767a;
527
+ }
528
+ }
529
+ }
530
+
531
+ // 下划线
532
+ &--underline-none {
533
+ text-decoration: none;
534
+ }
535
+
536
+ &--underline-hover {
537
+ text-decoration: none;
538
+
539
+ &:hover {
540
+ text-decoration: underline;
541
+ }
542
+ }
543
+
544
+ &--underline-always {
545
+ text-decoration: underline;
546
+ }
547
+
548
+ // 禁用状态
549
+ &--disabled {
550
+ cursor: not-allowed;
551
+ opacity: 0.6;
552
+ }
553
+
554
+ // 加载状态
555
+ &--loading {
556
+ cursor: wait;
557
+ opacity: 0.8;
558
+ }
559
+
560
+ // 悬停效果
561
+ &--hover {
562
+ opacity: 0.8;
563
+ }
564
+ }
565
+
566
+ .im-link__loading {
567
+ display: inline-flex;
568
+ align-items: center;
569
+ justify-content: center;
570
+ margin-right: 8rpx;
571
+
572
+ &-icon {
573
+ width: 20rpx;
574
+ height: 20rpx;
575
+ border: 2rpx solid currentColor;
576
+ border-top-color: transparent;
577
+ border-radius: 50%;
578
+ animation: im-link-rotate 1s linear infinite;
579
+ }
580
+ }
581
+
582
+ .im-link__icon {
583
+ display: inline-flex;
584
+ align-items: center;
585
+ justify-content: center;
586
+
587
+ &-text {
588
+ font-size: inherit;
589
+ line-height: 1;
590
+ }
591
+ }
592
+
593
+ .im-link__text {
594
+ line-height: 1.4;
595
+ white-space: nowrap;
596
+ }
597
+
598
+ .im-link__arrow {
599
+ display: inline-flex;
600
+ align-items: center;
601
+ justify-content: center;
602
+ transition: transform 0.3s;
603
+
604
+ .im-link:hover & {
605
+ transform: translateX(4rpx);
606
+ }
607
+
608
+ &-text {
609
+ font-size: inherit;
610
+ line-height: 1;
611
+ }
612
+ }
613
+
614
+ .im-link__badge {
615
+ position: absolute;
616
+ top: -8rpx;
617
+ right: -8rpx;
618
+ }
619
+
620
+ @keyframes im-link-rotate {
621
+ 0% {
622
+ transform: rotate(0deg);
623
+ }
624
+ 100% {
625
+ transform: rotate(360deg);
626
+ }
627
+ }
628
+ </style>
@@ -1,6 +1,9 @@
1
1
  <template>
2
2
  <view class="loading" :style="loadingStyle">
3
- <view class="rotate iconfont icon-loading" :style="icontStyle"></view>
3
+ <view :style="icontStyle">
4
+ <im-icon name="loading" :color="iconColor" :size="size" spin :spin-speed="2" />
5
+ <text class="loading-text">{{ text }}</text>
6
+ </view>
4
7
  <slot></slot>
5
8
  </view>
6
9
  </template>
@@ -12,16 +15,18 @@ interface Props {
12
15
  size?: number;
13
16
  iconColor?: string;
14
17
  mask?: boolean;
18
+ text?: string
15
19
  }
16
20
 
17
21
  const props = withDefaults(defineProps<Props>(), {
18
- size: 100,
22
+ size: 32,
19
23
  iconColor: '',
20
- mask: true
24
+ mask: true,
25
+ text: 'loading...'
21
26
  });
22
27
 
23
28
  const icontStyle = computed(() => {
24
- let style = `font-size:${props.size}rpx;`;
29
+ let style = `font-size:${props.size - 10}rpx; display:flex; align-items: center;`;
25
30
  if (props.iconColor) {
26
31
  style += `color: ${props.iconColor};`;
27
32
  } else if (props.mask) {
@@ -46,6 +51,10 @@ const loadingStyle = computed(() => {
46
51
  display: flex;
47
52
  justify-content: center;
48
53
  align-items: center;
54
+
55
+ &-text {
56
+ margin-left: 10rpx;
57
+ }
49
58
  }
50
59
 
51
60
  .rotate {
@@ -1,27 +1,27 @@
1
1
  <template>
2
- <u-popup ref="popup" mode="bottom" @open="onChange" @close="onChange">
2
+ <im-popup ref="popup" position="bottom" @open="onChange" @close="onChange">
3
3
  <view class="mention-picker">
4
4
  <view class="chat-at-top">
5
- <view class="chat-at-tip"> 选择要提醒的人</view>
6
- <button class="chat-at-btn" size="mini" @click="onClean()">清空 </button>
5
+ <view class="chat-at-tip">选择要提醒的人</view>
6
+ <button class="chat-at-btn" size="mini" @click="onClean()">清空</button>
7
7
  <button class="chat-at-btn" size="mini" @click="onOk()">确定({{ atUserIds.length }})
8
8
  </button>
9
9
  </view>
10
10
  <scroll-view v-show="atUserIds.length > 0" scroll-x="true" scroll-left="120">
11
11
  <view class="at-user-items">
12
12
  <view v-for="m in checkedMembers" class="at-user-item" :key="m.userId">
13
- <im-avatar :name="m.showNickName" :url="m.headImage" size="mini" />
13
+ <im-avatar :title="m.showNickName" :url="m.avatar" size="mini" />
14
14
  </view>
15
15
  </view>
16
16
  </scroll-view>
17
17
  <view class="search-bar">
18
- <u-search v-model="searchText" :show-action="false" shape="round" placeholder="搜索"></u-search>
18
+ <im-search v-model="searchText" :show-action="false" placeholder="搜索" />
19
19
  </view>
20
20
  <view class="member-items">
21
21
  <im-virtual-list :data="memberItems">
22
22
  <template v-slot="{ item }">
23
23
  <view class="member-item" @click="onSwitchChecked(item)">
24
- <im-avatar :name="item.showNickName" :online="item.online" :url="item.headImage"
24
+ <im-avatar :title="item.showNickName" :online="item.online" :url="item.avatar"
25
25
  size="small" />
26
26
  <view class="member-name">{{ item.showNickName }}</view>
27
27
  <radio :checked="item.checked" :disabled="item.locked"
@@ -31,7 +31,7 @@
31
31
  </im-virtual-list>
32
32
  </view>
33
33
  </view>
34
- </u-popup>
34
+ </im-popup>
35
35
  </template>
36
36
 
37
37
  <script setup lang="ts">
@@ -80,6 +80,7 @@ const init = (userId: number, atUserIds: number[]) => {
80
80
  };
81
81
 
82
82
  const open = () => {
83
+ console.log('打开')
83
84
  // 需要根据实际的 popup 引用调整
84
85
  popup.value.open();
85
86
  };