im-ui-mobile 0.0.96 → 0.0.99

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 (40) hide show
  1. package/components/im-avatar/im-avatar.vue +121 -121
  2. package/components/im-button/im-button.vue +630 -626
  3. package/components/im-cell/im-cell.vue +10 -15
  4. package/components/im-cell-group/im-cell-group.vue +16 -16
  5. package/components/im-chat-item/im-chat-item.vue +213 -213
  6. package/components/im-context-menu/im-context-menu.vue +138 -138
  7. package/components/im-file-upload/im-file-upload.vue +309 -309
  8. package/components/im-friend-item/im-friend-item.vue +82 -75
  9. package/components/im-group-item/im-group-item.vue +62 -62
  10. package/components/im-group-member-selector/im-group-member-selector.vue +202 -202
  11. package/components/im-group-rtc-join/im-group-rtc-join.vue +112 -112
  12. package/components/im-image-upload/im-image-upload.vue +94 -94
  13. package/components/im-loading/im-loading.vue +64 -64
  14. package/components/im-mention-picker/im-mention-picker.vue +191 -191
  15. package/components/im-message-item/im-message-item.vue +555 -555
  16. package/components/im-nav-bar/im-nav-bar.vue +98 -98
  17. package/components/im-read-receipt/im-read-receipt.vue +174 -174
  18. package/components/im-virtual-list/im-virtual-list.vue +51 -50
  19. package/components/im-voice-input/im-voice-input.vue +305 -304
  20. package/libs/index.ts +2 -3
  21. package/package.json +58 -58
  22. package/styles/button.scss +1 -1
  23. package/theme.scss +61 -62
  24. package/types/components.d.ts +0 -1
  25. package/types/index.d.ts +94 -94
  26. package/types/libs/index.d.ts +206 -204
  27. package/types/utils/datetime.d.ts +9 -9
  28. package/types/utils/dom.d.ts +11 -11
  29. package/types/utils/emoji.d.ts +8 -8
  30. package/types/utils/enums.d.ts +73 -73
  31. package/types/utils/messageType.d.ts +35 -35
  32. package/types/utils/recorderApp.d.ts +9 -9
  33. package/types/utils/recorderH5.d.ts +9 -9
  34. package/types/utils/requester.d.ts +15 -15
  35. package/types/utils/url.d.ts +5 -5
  36. package/types/utils/useDynamicRefs.d.ts +9 -9
  37. package/types/utils/websocket.d.ts +34 -34
  38. package/utils/enums.js +1 -1
  39. package/components/im-virtual-scroller/im-virtual-scroller.vue +0 -54
  40. package/types/components/virtual-scroller.d.ts +0 -20
@@ -1,99 +1,99 @@
1
- <template>
2
- <view class="nav-bar">
3
- <!-- #ifdef APP-PLUS -->
4
- <view style="height: var(--status-bar-height)"></view>
5
- <!-- #endif -->
6
- <view class="nav-bar-content">
7
- <!-- #ifndef MP-WEIXIN -->
8
- <view class="back" @click="handleBackClick" v-if="back">
9
- <u-icon name="arrow-left" :size="iconFontSize"></u-icon>
10
- </view>
11
- <!-- #endif -->
12
- <view class="title" v-if="title">
13
- <slot></slot>
14
- </view>
15
- <view class="btn">
16
- <u-icon class="btn-item" v-if="search" name="search" :size="iconFontSize"
17
- @click="$emit('search')"></u-icon>
18
- <u-icon class="btn-item" v-if="add" name="plus" :size="iconFontSize" @click="$emit('add')"></u-icon>
19
- <u-icon class="btn-item" v-if="more" name="more-dot-fill" :size="iconFontSize"
20
- @click="$emit('more')"></u-icon>
21
- </view>
22
- </view>
23
- </view>
24
- </template>
25
-
26
- <script setup lang="ts">
27
- interface Props {
28
- back?: boolean;
29
- title?: boolean;
30
- search?: boolean;
31
- add?: boolean;
32
- more?: boolean;
33
- iconFontSize?: number;
34
- }
35
-
36
- const props = withDefaults(defineProps<Props>(), {
37
- back: false,
38
- title: true,
39
- search: false,
40
- add: false,
41
- more: false,
42
- iconFontSize: 24
43
- });
44
-
45
- const handleBackClick = () => {
46
- uni.navigateBack({
47
- delta: 1
48
- });
49
- };
50
- </script>
51
-
52
- <style scoped lang="scss">
53
- .nav-bar {
54
- background: $im-bg-linear;
55
- position: fixed;
56
- top: 0;
57
- width: 100%;
58
- color: $im-text-color;
59
- border-bottom: 1px solid $im-border-light;
60
- font-size: $im-font-size-large;
61
- z-index: 99;
62
-
63
- .nav-bar-content {
64
- display: flex;
65
- align-items: center;
66
- justify-content: center;
67
- box-sizing: border-box;
68
- height: $im-nav-bar-height;
69
-
70
- .title {}
71
-
72
- .back {
73
- position: absolute;
74
- left: 0;
75
- height: 100%;
76
- display: flex;
77
- align-items: center;
78
- padding: 12px;
79
- font-size: 22px;
80
- box-sizing: border-box;
81
- }
82
-
83
- .btn {
84
- position: absolute;
85
- right: 0;
86
- height: 100%;
87
- display: flex;
88
- padding: 12px;
89
- align-items: center;
90
- box-sizing: border-box;
91
-
92
- .btn-item {
93
- margin-left: 8px;
94
- }
95
- }
96
- }
97
-
98
- }
1
+ <template>
2
+ <view class="nav-bar">
3
+ <!-- #ifdef APP-PLUS -->
4
+ <view style="height: var(--status-bar-height)"></view>
5
+ <!-- #endif -->
6
+ <view class="nav-bar-content">
7
+ <!-- #ifndef MP-WEIXIN -->
8
+ <view class="back" @click="handleBackClick" v-if="back">
9
+ <u-icon name="arrow-left" :size="iconFontSize"></u-icon>
10
+ </view>
11
+ <!-- #endif -->
12
+ <view class="title" v-if="title">
13
+ <slot></slot>
14
+ </view>
15
+ <view class="btn">
16
+ <u-icon class="btn-item" v-if="search" name="search" :size="iconFontSize"
17
+ @click="$emit('search')"></u-icon>
18
+ <u-icon class="btn-item" v-if="add" name="plus" :size="iconFontSize" @click="$emit('add')"></u-icon>
19
+ <u-icon class="btn-item" v-if="more" name="more-dot-fill" :size="iconFontSize"
20
+ @click="$emit('more')"></u-icon>
21
+ </view>
22
+ </view>
23
+ </view>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ interface Props {
28
+ back?: boolean;
29
+ title?: boolean;
30
+ search?: boolean;
31
+ add?: boolean;
32
+ more?: boolean;
33
+ iconFontSize?: number;
34
+ }
35
+
36
+ const props = withDefaults(defineProps<Props>(), {
37
+ back: false,
38
+ title: true,
39
+ search: false,
40
+ add: false,
41
+ more: false,
42
+ iconFontSize: 24
43
+ });
44
+
45
+ const handleBackClick = () => {
46
+ uni.navigateBack({
47
+ delta: 1
48
+ });
49
+ };
50
+ </script>
51
+
52
+ <style scoped lang="scss">
53
+ .nav-bar {
54
+ background: $im-bg-linear;
55
+ position: fixed;
56
+ top: 0;
57
+ width: 100%;
58
+ color: $im-text-color;
59
+ border-bottom: 1px solid $im-border-light;
60
+ font-size: $im-font-size-large;
61
+ z-index: 99;
62
+
63
+ .nav-bar-content {
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ box-sizing: border-box;
68
+ height: $im-nav-bar-height;
69
+
70
+ .title {}
71
+
72
+ .back {
73
+ position: absolute;
74
+ left: 0;
75
+ height: 100%;
76
+ display: flex;
77
+ align-items: center;
78
+ padding: 12px;
79
+ font-size: 22px;
80
+ box-sizing: border-box;
81
+ }
82
+
83
+ .btn {
84
+ position: absolute;
85
+ right: 0;
86
+ height: 100%;
87
+ display: flex;
88
+ padding: 12px;
89
+ align-items: center;
90
+ box-sizing: border-box;
91
+
92
+ .btn-item {
93
+ margin-left: 8px;
94
+ }
95
+ }
96
+ }
97
+
98
+ }
99
99
  </style>
@@ -1,175 +1,175 @@
1
- <template>
2
- <u-popup ref="popup" mode="bottom">
3
- <view class="read-receipt">
4
- <view class="uni-padding-wrap uni-common-mt">
5
- <u-tabs :current="current" :list="items" :show-bar="false" @change="onClickItem"></u-tabs>
6
- </view>
7
- <view class="content">
8
- <view v-if="current === 0">
9
- <im-virtual-scroller :items="readedMembers">
10
- <template v-slot="{ item }">
11
- <view class="member-item">
12
- <im-avatar :name="item.showNickName" :online="item.online" :url="item.headImage"
13
- :size="90" />
14
- <view class="member-name">{{ item.showNickName }}</view>
15
- </view>
16
- </template>
17
- </im-virtual-scroller>
18
- </view>
19
- <view v-if="current === 1">
20
- <im-virtual-scroller :items="unreadMembers">
21
- <template v-slot="{ item }">
22
- <view class="member-item">
23
- <im-avatar :name="item.showNickName" :online="item.online" :url="item.headImage"
24
- :size="90" />
25
- <view class="member-name">{{ item.showNickName }}</view>
26
- </view>
27
- </template>
28
- </im-virtual-scroller>
29
- </view>
30
- </view>
31
- </view>
32
- </u-popup>
33
- </template>
34
-
35
- <script setup lang="ts">
36
- import { ref } from 'vue'
37
- import ImAvatar from '../im-avatar/im-avatar.vue'
38
- import ImVirtualScroller from '../im-virtual-scroller/im-virtual-scroller.vue'
39
- import { Chat, Message } from '../../libs';
40
-
41
- interface Props {
42
- msgInfo: {
43
- groupId: number;
44
- id: number;
45
- sendId: number;
46
- };
47
- groupMembers: any[];
48
- }
49
-
50
- interface Member {
51
- userId: number;
52
- quit?: boolean;
53
- }
54
-
55
- const props = defineProps<Props>();
56
-
57
- const items = ref([{ name: '已读' }, { name: '未读' }]);
58
- const current = ref(0);
59
- const readedMembers = ref<Member[]>([]);
60
- const unreadMembers = ref<Member[]>([]);
61
- const popup = ref()
62
-
63
- interface Emits {
64
- (e: 'loaded', chatInfo: Chat, msgInfo: Message): void
65
- }
66
-
67
- const emit = defineEmits<Emits>()
68
-
69
- /**
70
- * @param userIds 已读用户IDs
71
- */
72
- const open = (userIds: number[]) => {
73
- popup.value.open();
74
- loadReadedUser(userIds);
75
- };
76
-
77
- const loadReadedUser = async (userIds: number[]) => {
78
- readedMembers.value = [];
79
- unreadMembers.value = [];
80
-
81
- try {
82
- // TODO:组件化
83
- // const response = await requestx.get<number[]>(`/message/group/findReadedUsers?groupId=${props.msgInfo.groupId}&messageId=${props.msgInfo.id}`);
84
- // const userIds = response.data;
85
-
86
- props.groupMembers.forEach((member: Member) => {
87
- // 发送者和已退群的不显示
88
- if (member.userId === props.msgInfo.sendId || member.quit) {
89
- return;
90
- }
91
- // 区分已读还是未读
92
- if (userIds.find((userId: number) => member.userId === userId)) {
93
- readedMembers.value.push(member);
94
- } else {
95
- unreadMembers.value.push(member);
96
- }
97
- });
98
-
99
- items.value[0] = { name: `已读(${readedMembers.value.length})` };
100
- items.value[1] = { name: `未读(${unreadMembers.value.length})` };
101
-
102
- const chatInfo: Chat = {
103
- type: 'GROUP',
104
- targetId: props.msgInfo.groupId,
105
- showName: '',
106
- headImage: '',
107
- isDnd: false,
108
- lastContent: '',
109
- unreadCount: 0,
110
- hotMinIdx: 0,
111
- readedMessageIdx: 0,
112
- messages: [],
113
- atMe: false,
114
- atAll: false,
115
- stored: false,
116
- delete: false
117
- };
118
-
119
- const msgInfo: Message = {
120
- id: props.msgInfo.id,
121
- groupId: props.msgInfo.groupId,
122
- readedCount: readedMembers.value.length,
123
- type: 0,
124
- content: ''
125
- };
126
-
127
- // TODO:组件化
128
- // 更新已读人数
129
- // chatStore.updateMessage(msgInfo, chatInfo);
130
- emit('loaded', chatInfo, msgInfo)
131
- } catch (error) {
132
- console.error('加载已读用户失败:', error);
133
- }
134
- };
135
-
136
- const onClickItem = (e: any) => {
137
- current.value = e.currentIndex;
138
- };
139
-
140
- defineExpose({
141
- open
142
- })
143
- </script>
144
-
145
- <style lang="scss" scoped>
146
- .read-receipt {
147
- position: relative;
148
- display: flex;
149
- flex-direction: column;
150
- background-color: white;
151
- padding: 10rpx;
152
-
153
- .member-item {
154
- height: 120rpx;
155
- display: flex;
156
- position: relative;
157
- padding: 0 30rpx;
158
- align-items: center;
159
- background-color: white;
160
- white-space: nowrap;
161
-
162
- .member-name {
163
- flex: 1;
164
- padding-left: 20rpx;
165
- font-size: 30rpx;
166
- font-weight: 600;
167
- line-height: 60rpx;
168
- white-space: nowrap;
169
- overflow: hidden;
170
- }
171
- }
172
-
173
-
174
- }
1
+ <template>
2
+ <u-popup ref="popup" mode="bottom">
3
+ <view class="read-receipt">
4
+ <view class="uni-padding-wrap uni-common-mt">
5
+ <u-tabs :current="current" :list="items" :show-bar="false" @change="onClickItem"></u-tabs>
6
+ </view>
7
+ <view class="content">
8
+ <view v-if="current === 0">
9
+ <im-virtual-list :data="readedMembers">
10
+ <template v-slot="{ item }">
11
+ <view class="member-item">
12
+ <im-avatar :name="item.showNickName" :online="item.online" :url="item.headImage"
13
+ :size="90" />
14
+ <view class="member-name">{{ item.showNickName }}</view>
15
+ </view>
16
+ </template>
17
+ </im-virtual-list>
18
+ </view>
19
+ <view v-if="current === 1">
20
+ <im-virtual-list :data="unreadMembers">
21
+ <template v-slot="{ item }">
22
+ <view class="member-item">
23
+ <im-avatar :name="item.showNickName" :online="item.online" :url="item.headImage"
24
+ :size="90" />
25
+ <view class="member-name">{{ item.showNickName }}</view>
26
+ </view>
27
+ </template>
28
+ </im-virtual-list>
29
+ </view>
30
+ </view>
31
+ </view>
32
+ </u-popup>
33
+ </template>
34
+
35
+ <script setup lang="ts">
36
+ import { ref } from 'vue'
37
+ import ImAvatar from '../im-avatar/im-avatar.vue'
38
+ import ImVirtualList from '../im-virtual-list/im-virtual-list.vue'
39
+ import { Chat, Message } from '../../libs';
40
+
41
+ interface Props {
42
+ msgInfo: {
43
+ groupId: number;
44
+ id: number;
45
+ sendId: number;
46
+ };
47
+ groupMembers: any[];
48
+ }
49
+
50
+ interface Member {
51
+ userId: number;
52
+ quit?: boolean;
53
+ }
54
+
55
+ const props = defineProps<Props>();
56
+
57
+ const items = ref([{ name: '已读' }, { name: '未读' }]);
58
+ const current = ref(0);
59
+ const readedMembers = ref<Member[]>([]);
60
+ const unreadMembers = ref<Member[]>([]);
61
+ const popup = ref()
62
+
63
+ interface Emits {
64
+ (e: 'loaded', chatInfo: Chat, msgInfo: Message): void
65
+ }
66
+
67
+ const emit = defineEmits<Emits>()
68
+
69
+ /**
70
+ * @param userIds 已读用户IDs
71
+ */
72
+ const open = (userIds: number[]) => {
73
+ popup.value.open();
74
+ loadReadedUser(userIds);
75
+ };
76
+
77
+ const loadReadedUser = async (userIds: number[]) => {
78
+ readedMembers.value = [];
79
+ unreadMembers.value = [];
80
+
81
+ try {
82
+ // TODO:组件化
83
+ // const response = await requestx.get<number[]>(`/message/group/findReadedUsers?groupId=${props.msgInfo.groupId}&messageId=${props.msgInfo.id}`);
84
+ // const userIds = response.data;
85
+
86
+ props.groupMembers.forEach((member: Member) => {
87
+ // 发送者和已退群的不显示
88
+ if (member.userId === props.msgInfo.sendId || member.quit) {
89
+ return;
90
+ }
91
+ // 区分已读还是未读
92
+ if (userIds.find((userId: number) => member.userId === userId)) {
93
+ readedMembers.value.push(member);
94
+ } else {
95
+ unreadMembers.value.push(member);
96
+ }
97
+ });
98
+
99
+ items.value[0] = { name: `已读(${readedMembers.value.length})` };
100
+ items.value[1] = { name: `未读(${unreadMembers.value.length})` };
101
+
102
+ const chatInfo: Chat = {
103
+ type: 'GROUP',
104
+ targetId: props.msgInfo.groupId,
105
+ showName: '',
106
+ headImage: '',
107
+ isDnd: false,
108
+ lastContent: '',
109
+ unreadCount: 0,
110
+ hotMinIdx: 0,
111
+ readedMessageIdx: 0,
112
+ messages: [],
113
+ atMe: false,
114
+ atAll: false,
115
+ stored: false,
116
+ delete: false
117
+ };
118
+
119
+ const msgInfo: Message = {
120
+ id: props.msgInfo.id,
121
+ groupId: props.msgInfo.groupId,
122
+ readedCount: readedMembers.value.length,
123
+ type: 0,
124
+ content: ''
125
+ };
126
+
127
+ // TODO:组件化
128
+ // 更新已读人数
129
+ // chatStore.updateMessage(msgInfo, chatInfo);
130
+ emit('loaded', chatInfo, msgInfo)
131
+ } catch (error) {
132
+ console.error('加载已读用户失败:', error);
133
+ }
134
+ };
135
+
136
+ const onClickItem = (e: any) => {
137
+ current.value = e.currentIndex;
138
+ };
139
+
140
+ defineExpose({
141
+ open
142
+ })
143
+ </script>
144
+
145
+ <style lang="scss" scoped>
146
+ .read-receipt {
147
+ position: relative;
148
+ display: flex;
149
+ flex-direction: column;
150
+ background-color: white;
151
+ padding: 10rpx;
152
+
153
+ .member-item {
154
+ height: 120rpx;
155
+ display: flex;
156
+ position: relative;
157
+ padding: 0 30rpx;
158
+ align-items: center;
159
+ background-color: white;
160
+ white-space: nowrap;
161
+
162
+ .member-name {
163
+ flex: 1;
164
+ padding-left: 20rpx;
165
+ font-size: 30rpx;
166
+ font-weight: 600;
167
+ line-height: 60rpx;
168
+ white-space: nowrap;
169
+ overflow: hidden;
170
+ }
171
+ }
172
+
173
+
174
+ }
175
175
  </style>