im-ui-mobile 0.0.98 → 0.1.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 (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 +52 -51
  19. package/components/im-voice-input/im-voice-input.vue +305 -305
  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,203 +1,203 @@
1
- <template>
2
- <u-popup ref="popup" mode="bottom">
3
- <view class="group-member-selector">
4
- <view class="top-bar">
5
- <view class="top-tip">选择成员</view>
6
- <button class="top-btn" size="mini" @click="onClean()">清空 </button>
7
- <button class="top-btn" size="mini" @click="onOk()">确定({{ checkedIds.length }})
8
- </button>
9
- </view>
10
- <scroll-view v-show="checkedIds.length > 0" scroll-x="true" scroll-left="120">
11
- <view class="checked-users">
12
- <view v-for="m in checkedMembers" class="user-item" :key="m.userId">
13
- <im-avatar :name="m.showNickName" :url="m.headImage" :size="60" />
14
- </view>
15
- </view>
16
- </scroll-view>
17
- <view class="search-bar">
18
- <u-search v-model="searchText" :show-action="false" placeholder="搜索"></u-search>
19
- </view>
20
- <view class="member-items">
21
- <im-virtual-scroller :items="showMembers">
22
- <template v-slot="{ item }">
23
- <view class="member-item" @click="onSwitchChecked(item)">
24
- <im-avatar :name="item.showNickName" :online="item.online" :url="item.headImage"
25
- :size="90" />
26
- <view class="member-name">{{ item.showNickName }}
27
- </view>
28
- <view class="member-checked">
29
- <radio :checked="item.checked" :disabled="item.locked"
30
- @click.stop="onSwitchChecked(item)" />
31
- </view>
32
- </view>
33
- </template>
34
- </im-virtual-scroller>
35
- </view>
36
- </view>
37
- </u-popup>
38
- </template>
39
-
40
-
41
- <script setup lang="ts">
42
- import { ref, computed } from 'vue'
43
- import ImAvatar from '../im-avatar/im-avatar.vue'
44
- import ImVirtualScroller from '../im-virtual-scroller/im-virtual-scroller.vue'
45
-
46
- interface Props {
47
- group?: any;
48
- members?: any[];
49
- maxSize?: number;
50
- }
51
-
52
- interface Emits {
53
- (e: 'complete', userIds: number[]): void;
54
- }
55
-
56
- interface Member {
57
- userId: number;
58
- checked?: boolean;
59
- locked?: boolean;
60
- hide?: boolean;
61
- quit?: boolean;
62
- showNickName: string;
63
- }
64
-
65
- const props = withDefaults(defineProps<Props>(), {
66
- members: () => [],
67
- maxSize: 50
68
- });
69
-
70
- const emit = defineEmits<Emits>();
71
-
72
- const searchText = ref("");
73
- const popup = ref() // 组件引用
74
-
75
- const init = (checkedIds: number[], lockedIds: number[], hideIds: number[]) => {
76
- props.members.forEach((m: Member) => {
77
- m.checked = checkedIds.includes(m.userId);
78
- m.locked = lockedIds.includes(m.userId);
79
- m.hide = hideIds.includes(m.userId);
80
- });
81
- };
82
-
83
- const open = () => {
84
- popup.value.open();
85
- };
86
-
87
- const onSwitchChecked = (m: Member) => {
88
- if (!m.locked) {
89
- m.checked = !m.checked;
90
- }
91
- // 达到选择上限
92
- if (props.maxSize > 0 && checkedIds.value.length > props.maxSize) {
93
- m.checked = false;
94
- uni.showToast({
95
- title: `最多选择${props.maxSize}位用户`,
96
- icon: "none"
97
- });
98
- }
99
- };
100
-
101
- const onClean = () => {
102
- props.members.forEach((m: Member) => {
103
- if (!m.locked && m.checked) {
104
- m.checked = false;
105
- }
106
- });
107
- };
108
-
109
- const onOk = () => {
110
- // this.$refs.popup.close();
111
- emit("complete", checkedIds.value);
112
- };
113
-
114
- const checkedIds = computed(() => {
115
- return checkedMembers.value.map(m => m.userId);
116
- });
117
-
118
- const checkedMembers = computed(() => {
119
- return props.members.filter((m: Member) => !m.quit && !m.hide && m.checked);
120
- });
121
-
122
- const showMembers = computed(() => {
123
- return props.members.filter((m: Member) =>
124
- !m.quit && !m.hide && m.showNickName.includes(searchText.value)
125
- );
126
- });
127
-
128
- defineExpose({
129
- init,
130
- open
131
- })
132
- </script>
133
-
134
-
135
- <style lang="scss" scoped>
136
- .group-member-selector {
137
- position: relative;
138
- display: flex;
139
- flex-direction: column;
140
- background-color: white;
141
- padding: 10rpx;
142
- border-radius: 15rpx 15rpx 0 0;
143
- overflow: hidden;
144
-
145
- .top-bar {
146
- display: flex;
147
- align-items: center;
148
- height: 70rpx;
149
- padding: 10rpx 30rpx;
150
-
151
- .top-tip {
152
- flex: 1;
153
- }
154
-
155
- .top-btn {
156
- margin-left: 10rpx;
157
- }
158
- }
159
-
160
- .checked-users {
161
- display: flex;
162
- align-items: center;
163
- height: 90rpx;
164
- padding: 0 30rpx;
165
-
166
- .user-item {
167
- padding: 3rpx;
168
- }
169
- }
170
-
171
- .member-items {
172
- position: relative;
173
- flex: 1;
174
- overflow: hidden;
175
-
176
- .member-item {
177
- height: 120rpx;
178
- display: flex;
179
- position: relative;
180
- padding: 0 30rpx;
181
- align-items: center;
182
- background-color: white;
183
- white-space: nowrap;
184
-
185
- .member-name {
186
- display: flex;
187
- align-items: center;
188
- flex: 1;
189
- padding-left: 20rpx;
190
- font-size: 30rpx;
191
- font-weight: 600;
192
- line-height: 60rpx;
193
- white-space: nowrap;
194
- overflow: hidden;
195
-
196
- .uni-tag {
197
- margin-left: 5rpx;
198
- }
199
- }
200
- }
201
- }
202
- }
1
+ <template>
2
+ <u-popup ref="popup" mode="bottom">
3
+ <view class="group-member-selector">
4
+ <view class="top-bar">
5
+ <view class="top-tip">选择成员</view>
6
+ <button class="top-btn" size="mini" @click="onClean()">清空 </button>
7
+ <button class="top-btn" size="mini" @click="onOk()">确定({{ checkedIds.length }})
8
+ </button>
9
+ </view>
10
+ <scroll-view v-show="checkedIds.length > 0" scroll-x="true" scroll-left="120">
11
+ <view class="checked-users">
12
+ <view v-for="m in checkedMembers" class="user-item" :key="m.userId">
13
+ <im-avatar :name="m.showNickName" :url="m.headImage" :size="60" />
14
+ </view>
15
+ </view>
16
+ </scroll-view>
17
+ <view class="search-bar">
18
+ <u-search v-model="searchText" :show-action="false" placeholder="搜索"></u-search>
19
+ </view>
20
+ <view class="member-items">
21
+ <im-virtual-list :data="showMembers">
22
+ <template v-slot="{ item }">
23
+ <view class="member-item" @click="onSwitchChecked(item)">
24
+ <im-avatar :name="item.showNickName" :online="item.online" :url="item.headImage"
25
+ :size="90" />
26
+ <view class="member-name">{{ item.showNickName }}
27
+ </view>
28
+ <view class="member-checked">
29
+ <radio :checked="item.checked" :disabled="item.locked"
30
+ @click.stop="onSwitchChecked(item)" />
31
+ </view>
32
+ </view>
33
+ </template>
34
+ </im-virtual-list>
35
+ </view>
36
+ </view>
37
+ </u-popup>
38
+ </template>
39
+
40
+
41
+ <script setup lang="ts">
42
+ import { ref, computed } from 'vue'
43
+ import ImAvatar from '../im-avatar/im-avatar.vue'
44
+ import ImVirtualList from '../im-virtual-list/im-virtual-list.vue'
45
+
46
+ interface Props {
47
+ group?: any;
48
+ members?: any[];
49
+ maxSize?: number;
50
+ }
51
+
52
+ interface Emits {
53
+ (e: 'complete', userIds: number[]): void;
54
+ }
55
+
56
+ interface Member {
57
+ userId: number;
58
+ checked?: boolean;
59
+ locked?: boolean;
60
+ hide?: boolean;
61
+ quit?: boolean;
62
+ showNickName: string;
63
+ }
64
+
65
+ const props = withDefaults(defineProps<Props>(), {
66
+ members: () => [],
67
+ maxSize: 50
68
+ });
69
+
70
+ const emit = defineEmits<Emits>();
71
+
72
+ const searchText = ref("");
73
+ const popup = ref() // 组件引用
74
+
75
+ const init = (checkedIds: number[], lockedIds: number[], hideIds: number[]) => {
76
+ props.members.forEach((m: Member) => {
77
+ m.checked = checkedIds.includes(m.userId);
78
+ m.locked = lockedIds.includes(m.userId);
79
+ m.hide = hideIds.includes(m.userId);
80
+ });
81
+ };
82
+
83
+ const open = () => {
84
+ popup.value.open();
85
+ };
86
+
87
+ const onSwitchChecked = (m: Member) => {
88
+ if (!m.locked) {
89
+ m.checked = !m.checked;
90
+ }
91
+ // 达到选择上限
92
+ if (props.maxSize > 0 && checkedIds.value.length > props.maxSize) {
93
+ m.checked = false;
94
+ uni.showToast({
95
+ title: `最多选择${props.maxSize}位用户`,
96
+ icon: "none"
97
+ });
98
+ }
99
+ };
100
+
101
+ const onClean = () => {
102
+ props.members.forEach((m: Member) => {
103
+ if (!m.locked && m.checked) {
104
+ m.checked = false;
105
+ }
106
+ });
107
+ };
108
+
109
+ const onOk = () => {
110
+ // this.$refs.popup.close();
111
+ emit("complete", checkedIds.value);
112
+ };
113
+
114
+ const checkedIds = computed(() => {
115
+ return checkedMembers.value.map(m => m.userId);
116
+ });
117
+
118
+ const checkedMembers = computed(() => {
119
+ return props.members.filter((m: Member) => !m.quit && !m.hide && m.checked);
120
+ });
121
+
122
+ const showMembers = computed(() => {
123
+ return props.members.filter((m: Member) =>
124
+ !m.quit && !m.hide && m.showNickName.includes(searchText.value)
125
+ );
126
+ });
127
+
128
+ defineExpose({
129
+ init,
130
+ open
131
+ })
132
+ </script>
133
+
134
+
135
+ <style lang="scss" scoped>
136
+ .group-member-selector {
137
+ position: relative;
138
+ display: flex;
139
+ flex-direction: column;
140
+ background-color: white;
141
+ padding: 10rpx;
142
+ border-radius: 15rpx 15rpx 0 0;
143
+ overflow: hidden;
144
+
145
+ .top-bar {
146
+ display: flex;
147
+ align-items: center;
148
+ height: 70rpx;
149
+ padding: 10rpx 30rpx;
150
+
151
+ .top-tip {
152
+ flex: 1;
153
+ }
154
+
155
+ .top-btn {
156
+ margin-left: 10rpx;
157
+ }
158
+ }
159
+
160
+ .checked-users {
161
+ display: flex;
162
+ align-items: center;
163
+ height: 90rpx;
164
+ padding: 0 30rpx;
165
+
166
+ .user-item {
167
+ padding: 3rpx;
168
+ }
169
+ }
170
+
171
+ .member-items {
172
+ position: relative;
173
+ flex: 1;
174
+ overflow: hidden;
175
+
176
+ .member-item {
177
+ height: 120rpx;
178
+ display: flex;
179
+ position: relative;
180
+ padding: 0 30rpx;
181
+ align-items: center;
182
+ background-color: white;
183
+ white-space: nowrap;
184
+
185
+ .member-name {
186
+ display: flex;
187
+ align-items: center;
188
+ flex: 1;
189
+ padding-left: 20rpx;
190
+ font-size: 30rpx;
191
+ font-weight: 600;
192
+ line-height: 60rpx;
193
+ white-space: nowrap;
194
+ overflow: hidden;
195
+
196
+ .uni-tag {
197
+ margin-left: 5rpx;
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
203
  </style>
@@ -1,113 +1,113 @@
1
- <template>
2
- <u-popup ref="popup" mode="center">
3
- <u-modal :show="true" :zoom="false" :async-close="false" title="是否加入通话?" confirm-text="加入" @confirm="onOk">
4
- <div class="group-rtc-join">
5
- <div class="host-info">
6
- <div>发起人</div>
7
- <im-avatar :name="rtcInfo.host.nickName" :url="rtcInfo.host.headImage" :size="80" />
8
- </div>
9
- <div class="user-info">
10
- <div>{{ rtcInfo.userInfos.length + '人正在通话中' }}</div>
11
- <scroll-view scroll-x="true" scroll-left="120">
12
- <view class="user-list">
13
- <view v-for="user in rtcInfo.userInfos" class="user-item" :key="user.id">
14
- <im-avatar :name="user.nickName" :url="user.headImage" :size="80" />
15
- </view>
16
- </view>
17
- </scroll-view>
18
- </div>
19
- </div>
20
- </u-modal>
21
- </u-popup>
22
- </template>
23
-
24
- <script setup lang="ts">
25
- import ImAvatar from '../im-avatar/im-avatar.vue'
26
- import { ref } from 'vue';
27
- import { UserInfo } from '../../libs';
28
-
29
- interface Props {
30
- groupId?: number;
31
- }
32
-
33
- interface RtcInfo {
34
- userInfos: Array<{
35
- id: number;
36
- nickName: string;
37
- headImage: string;
38
- isCamera?: boolean;
39
- isMicroPhone?: boolean;
40
- }>,
41
- host: any
42
- }
43
-
44
- const props = defineProps<Props>();
45
-
46
- const rtcInfo = ref<RtcInfo>({ userInfos: [], host: {} });
47
- const userInfo = ref<UserInfo>()
48
-
49
- interface Emits {
50
- (e: 'ok', groupId: number, inviterId: number, userInfos: string): void
51
- }
52
- const emit = defineEmits<Emits>()
53
-
54
- const open = (userInfo1: UserInfo, rtcInfoData: RtcInfo) => {
55
- userInfo.value = userInfo1;
56
- rtcInfo.value = rtcInfoData;
57
- };
58
-
59
- const onOk = () => {
60
- const users = [...rtcInfo.value.userInfos];
61
- const mine = userInfo.value as UserInfo // useUserStore().userInfo;
62
-
63
- // 加入自己的信息
64
- if (!users.find((user) => user.id === mine.id)) {
65
- users.push({
66
- id: mine.id,
67
- nickName: mine.nickName,
68
- headImage: String(mine.headImageThumb),
69
- isCamera: false,
70
- isMicroPhone: true
71
- });
72
- }
73
-
74
- const userInfos = encodeURIComponent(JSON.stringify(users));
75
-
76
- // TODO:组件化
77
- // uni.navigateTo({
78
- // url: `/pages-chat/pages/chat/chat-group-video?groupId=${props.groupId}&isHost=false&inviterId=${mine.id}&userInfos=${userInfos}`
79
- // });
80
-
81
- emit('ok', Number(props.groupId), mine.id, userInfos)
82
- };
83
-
84
- defineExpose({
85
- open
86
- })
87
- </script>
88
-
89
- <style lang="scss" scoped>
90
- .group-rtc-join {
91
- width: 100%;
92
-
93
- .host-info {
94
- font-size: 16px;
95
- padding: 10px;
96
- }
97
-
98
- .user-info {
99
- font-size: 16px;
100
- padding: 10px;
101
- }
102
-
103
- .user-list {
104
- display: flex;
105
- align-items: center;
106
- height: 90rpx;
107
-
108
- .user-item {
109
- padding: 3rpx;
110
- }
111
- }
112
- }
1
+ <template>
2
+ <u-popup ref="popup" mode="center">
3
+ <u-modal :show="true" :zoom="false" :async-close="false" title="是否加入通话?" confirm-text="加入" @confirm="onOk">
4
+ <div class="group-rtc-join">
5
+ <div class="host-info">
6
+ <div>发起人</div>
7
+ <im-avatar :name="rtcInfo.host.nickName" :url="rtcInfo.host.headImage" :size="80" />
8
+ </div>
9
+ <div class="user-info">
10
+ <div>{{ rtcInfo.userInfos.length + '人正在通话中' }}</div>
11
+ <scroll-view scroll-x="true" scroll-left="120">
12
+ <view class="user-list">
13
+ <view v-for="user in rtcInfo.userInfos" class="user-item" :key="user.id">
14
+ <im-avatar :name="user.nickName" :url="user.headImage" :size="80" />
15
+ </view>
16
+ </view>
17
+ </scroll-view>
18
+ </div>
19
+ </div>
20
+ </u-modal>
21
+ </u-popup>
22
+ </template>
23
+
24
+ <script setup lang="ts">
25
+ import ImAvatar from '../im-avatar/im-avatar.vue'
26
+ import { ref } from 'vue';
27
+ import { UserInfo } from '../../libs';
28
+
29
+ interface Props {
30
+ groupId?: number;
31
+ }
32
+
33
+ interface RtcInfo {
34
+ userInfos: Array<{
35
+ id: number;
36
+ nickName: string;
37
+ headImage: string;
38
+ isCamera?: boolean;
39
+ isMicroPhone?: boolean;
40
+ }>,
41
+ host: any
42
+ }
43
+
44
+ const props = defineProps<Props>();
45
+
46
+ const rtcInfo = ref<RtcInfo>({ userInfos: [], host: {} });
47
+ const userInfo = ref<UserInfo>()
48
+
49
+ interface Emits {
50
+ (e: 'ok', groupId: number, inviterId: number, userInfos: string): void
51
+ }
52
+ const emit = defineEmits<Emits>()
53
+
54
+ const open = (userInfo1: UserInfo, rtcInfoData: RtcInfo) => {
55
+ userInfo.value = userInfo1;
56
+ rtcInfo.value = rtcInfoData;
57
+ };
58
+
59
+ const onOk = () => {
60
+ const users = [...rtcInfo.value.userInfos];
61
+ const mine = userInfo.value as UserInfo // useUserStore().userInfo;
62
+
63
+ // 加入自己的信息
64
+ if (!users.find((user) => user.id === mine.id)) {
65
+ users.push({
66
+ id: mine.id,
67
+ nickName: mine.nickName,
68
+ headImage: String(mine.headImageThumb),
69
+ isCamera: false,
70
+ isMicroPhone: true
71
+ });
72
+ }
73
+
74
+ const userInfos = encodeURIComponent(JSON.stringify(users));
75
+
76
+ // TODO:组件化
77
+ // uni.navigateTo({
78
+ // url: `/pages-chat/pages/chat/chat-group-video?groupId=${props.groupId}&isHost=false&inviterId=${mine.id}&userInfos=${userInfos}`
79
+ // });
80
+
81
+ emit('ok', Number(props.groupId), mine.id, userInfos)
82
+ };
83
+
84
+ defineExpose({
85
+ open
86
+ })
87
+ </script>
88
+
89
+ <style lang="scss" scoped>
90
+ .group-rtc-join {
91
+ width: 100%;
92
+
93
+ .host-info {
94
+ font-size: 16px;
95
+ padding: 10px;
96
+ }
97
+
98
+ .user-info {
99
+ font-size: 16px;
100
+ padding: 10px;
101
+ }
102
+
103
+ .user-list {
104
+ display: flex;
105
+ align-items: center;
106
+ height: 90rpx;
107
+
108
+ .user-item {
109
+ padding: 3rpx;
110
+ }
111
+ }
112
+ }
113
113
  </style>