im-ui-mobile 0.0.7 → 0.0.9

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 (64) hide show
  1. package/package.json +10 -7
  2. package/src/components/chat-box/index.vue +203 -0
  3. package/src/components/chat-item/index.vue +185 -0
  4. package/src/components/chat-message-item/index.vue +205 -0
  5. package/src/index.js +31 -0
  6. package/src/libs/index.ts +182 -0
  7. package/src/libs/recorder.ts +21 -0
  8. package/src/libs/user.ts +19 -0
  9. package/src/types/components/chat-box/index.vue.d.ts +129 -0
  10. package/src/types/components/chat-item/index.vue.d.ts +64 -0
  11. package/src/types/components/chat-message-item/index.vue.d.ts +73 -0
  12. package/src/types/index.d.ts +9 -0
  13. package/{types → src/types}/utils/index.d.ts +1 -1
  14. package/{utils → src/utils}/index.ts +1 -1
  15. package/components/chat-box/index.vue +0 -167
  16. package/components/chat-item/index.vue +0 -105
  17. package/components/chat-message-item/index.vue +0 -129
  18. package/types/components/chat-box/index.vue.d.ts +0 -68
  19. package/types/components/chat-item/index.vue.d.ts +0 -43
  20. package/types/components/chat-message-item/index.vue.d.ts +0 -49
  21. package/types/index.d.ts +0 -11
  22. /package/{types → src/types}/libs/index.d.ts +0 -0
  23. /package/{types → src/types}/libs/recorder.d.ts +0 -0
  24. /package/{types → src/types}/libs/user.d.ts +0 -0
  25. /package/{types → src/types}/utils/auth.d.ts +0 -0
  26. /package/{types → src/types}/utils/datetime.d.ts +0 -0
  27. /package/{types → src/types}/utils/emotion.d.ts +0 -0
  28. /package/{types → src/types}/utils/enums.d.ts +0 -0
  29. /package/{types → src/types}/utils/env.d.ts +0 -0
  30. /package/{types → src/types}/utils/eventBus/EventBusImpl.d.ts +0 -0
  31. /package/{types → src/types}/utils/eventBus/EventCallback.d.ts +0 -0
  32. /package/{types → src/types}/utils/eventBus/GlobalEventCallback.d.ts +0 -0
  33. /package/{types → src/types}/utils/eventBus/IEventBus.d.ts +0 -0
  34. /package/{types → src/types}/utils/eventBus/IEventListener.d.ts +0 -0
  35. /package/{types → src/types}/utils/eventBus/index.d.ts +0 -0
  36. /package/{types → src/types}/utils/htmlEscape.d.ts +0 -0
  37. /package/{types → src/types}/utils/messageType.d.ts +0 -0
  38. /package/{types → src/types}/utils/recorderApp.d.ts +0 -0
  39. /package/{types → src/types}/utils/recorderH5.d.ts +0 -0
  40. /package/{types → src/types}/utils/request.d.ts +0 -0
  41. /package/{types → src/types}/utils/requestx.d.ts +0 -0
  42. /package/{types → src/types}/utils/url.d.ts +0 -0
  43. /package/{types → src/types}/utils/useDynamicRefs.d.ts +0 -0
  44. /package/{types → src/types}/utils/websocket.d.ts +0 -0
  45. /package/{utils → src/utils}/auth.ts +0 -0
  46. /package/{utils → src/utils}/datetime.ts +0 -0
  47. /package/{utils → src/utils}/emotion.ts +0 -0
  48. /package/{utils → src/utils}/enums.ts +0 -0
  49. /package/{utils → src/utils}/env.ts +0 -0
  50. /package/{utils → src/utils}/eventBus/EventBusImpl.ts +0 -0
  51. /package/{utils → src/utils}/eventBus/EventCallback.ts +0 -0
  52. /package/{utils → src/utils}/eventBus/GlobalEventCallback.ts +0 -0
  53. /package/{utils → src/utils}/eventBus/IEventBus.ts +0 -0
  54. /package/{utils → src/utils}/eventBus/IEventListener.ts +0 -0
  55. /package/{utils → src/utils}/eventBus/index.ts +0 -0
  56. /package/{utils → src/utils}/htmlEscape.ts +0 -0
  57. /package/{utils → src/utils}/messageType.ts +0 -0
  58. /package/{utils → src/utils}/recorderApp.ts +0 -0
  59. /package/{utils → src/utils}/recorderH5.ts +0 -0
  60. /package/{utils → src/utils}/request.ts +0 -0
  61. /package/{utils → src/utils}/requestx.ts +0 -0
  62. /package/{utils → src/utils}/url.ts +0 -0
  63. /package/{utils → src/utils}/useDynamicRefs.ts +0 -0
  64. /package/{utils → src/utils}/websocket.ts +0 -0
package/package.json CHANGED
@@ -1,22 +1,25 @@
1
1
  {
2
2
  "name": "im-ui-mobile",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "A Vue3.0 + typescript instant messaging component library for Uniapp",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
7
7
  "files": [
8
- "components",
9
- "types",
10
- "utils",
11
- "index.js"
8
+ "/src/components",
9
+ "/src/libs",
10
+ "/src/types",
11
+ "/src/utils",
12
+ "/src/index.js"
12
13
  ],
13
14
  "scripts": {
14
- "dev": "vite",
15
- "build": "npm run build:types",
15
+ "dev": "cd examples && npm run dev:h5",
16
+ "build": "npm run build:types",
16
17
  "build:types": "vue-tsc -p tsconfig.build.json",
18
+ "clean:types": "rmdir /s /q src/types 2>nul # '删除 types 目录'",
17
19
  "prepublishOnly": "npm run build"
18
20
  },
19
21
  "devDependencies": {
22
+ "@dcloudio/uni-app": "3.0.0-4070520250711001",
20
23
  "@dcloudio/types": "^3.4.8",
21
24
  "@dcloudio/uni-cli-shared": "3.0.0-4070520250711001",
22
25
  "@dcloudio/vite-plugin-uni": "3.0.0-4070520250711001",
@@ -0,0 +1,203 @@
1
+ <template>
2
+ <view class="u-im-chat-box">
3
+ <view class="u-im-chat-box__header">
4
+ <view class="u-im-chat-box__title">{{ title }}</view>
5
+ <view class="u-im-chat-box__actions">
6
+ <slot name="header-actions"></slot>
7
+ </view>
8
+ </view>
9
+
10
+ <view class="u-im-chat-box__messages" ref="messagesRef">
11
+ <view class="u-im-chat-box__loading" v-if="loading">
12
+ <!-- 替换 uview 组件 -->
13
+ <view class="loading-icon">加载中...</view>
14
+ </view>
15
+ <chat-message-item
16
+ v-for="(message, index) in messages"
17
+ :key="message.id || index"
18
+ :position="message.position"
19
+ :type="message.type"
20
+ :content="message.content"
21
+ :avatar="message.avatar"
22
+ :show-avatar="shouldShowAvatar(message, index)"
23
+ :status="message.status"
24
+ :duration="message.duration"
25
+ />
26
+ </view>
27
+
28
+ <view class="u-im-chat-box__input">
29
+ <view class="u-im-chat-box__tools">
30
+ <slot name="input-tools"></slot>
31
+ </view>
32
+ <view class="u-im-chat-box__textarea">
33
+ <!-- 替换 u-textarea -->
34
+ <textarea
35
+ v-model="inputText"
36
+ :placeholder="placeholder"
37
+ :maxlength="maxlength"
38
+ :auto-height="true"
39
+ @confirm="handleSend"
40
+ class="chat-textarea"
41
+ />
42
+ </view>
43
+ <view class="u-im-chat-box__send">
44
+ <!-- 替换 u-button -->
45
+ <button type="primary" size="mini" @click="handleSend" class="send-button">发送</button>
46
+ </view>
47
+ </view>
48
+ </view>
49
+ </template>
50
+
51
+ <script>
52
+ import ChatMessageItem from '../chat-message-item/index.vue'
53
+
54
+ export default {
55
+ name: 'ChatBox',
56
+ components: {
57
+ ChatMessageItem
58
+ },
59
+ props: {
60
+ title: {
61
+ type: String,
62
+ default: '聊天'
63
+ },
64
+ messages: {
65
+ type: Array,
66
+ default: () => []
67
+ },
68
+ placeholder: {
69
+ type: String,
70
+ default: '请输入消息...'
71
+ },
72
+ maxlength: {
73
+ type: Number,
74
+ default: 1000
75
+ },
76
+ loading: {
77
+ type: Boolean,
78
+ default: false
79
+ }
80
+ },
81
+ data() {
82
+ return {
83
+ inputText: ''
84
+ }
85
+ },
86
+ watch: {
87
+ messages: {
88
+ handler() {
89
+ this.scrollToBottom()
90
+ },
91
+ deep: true
92
+ }
93
+ },
94
+ mounted() {
95
+ this.scrollToBottom()
96
+ },
97
+ methods: {
98
+ handleSend() {
99
+ if (this.inputText.trim()) {
100
+ this.$emit('send', this.inputText.trim())
101
+ this.inputText = ''
102
+ }
103
+ },
104
+ shouldShowAvatar(message, index) {
105
+ if (index === 0) return true
106
+ const prevMessage = this.messages[index - 1]
107
+ return prevMessage.position !== message.position ||
108
+ prevMessage.avatar !== message.avatar ||
109
+ (message.timestamp && prevMessage.timestamp &&
110
+ message.timestamp - prevMessage.timestamp > 300000) // 5分钟
111
+ },
112
+ scrollToBottom() {
113
+ this.$nextTick(() => {
114
+ if (this.$refs.messagesRef) {
115
+ this.$refs.messagesRef.scrollTop = this.$refs.messagesRef.scrollHeight
116
+ }
117
+ })
118
+ }
119
+ }
120
+ }
121
+ </script>
122
+
123
+ <style scoped>
124
+ .u-im-chat-box {
125
+ display: flex;
126
+ flex-direction: column;
127
+ height: 1200rpx;
128
+ border: 2rpx solid #e4e7ed;
129
+ border-radius: 16rpx;
130
+ overflow: hidden;
131
+ }
132
+
133
+ .u-im-chat-box__header {
134
+ display: flex;
135
+ justify-content: space-between;
136
+ align-items: center;
137
+ padding: 24rpx 32rpx;
138
+ background-color: #f5f7fa;
139
+ border-bottom: 2rpx solid #e4e7ed;
140
+ }
141
+
142
+ .u-im-chat-box__title {
143
+ font-size: 32rpx;
144
+ font-weight: 500;
145
+ color: #303133;
146
+ }
147
+
148
+ .u-im-chat-box__messages {
149
+ flex: 1;
150
+ padding: 32rpx;
151
+ overflow-y: auto;
152
+ background-color: #fafafa;
153
+ }
154
+
155
+ .u-im-chat-box__loading {
156
+ display: flex;
157
+ justify-content: center;
158
+ padding: 32rpx;
159
+ }
160
+
161
+ .loading-icon {
162
+ font-size: 28rpx;
163
+ color: #909399;
164
+ }
165
+
166
+ .u-im-chat-box__input {
167
+ border-top: 2rpx solid #e4e7ed;
168
+ background-color: #fff;
169
+ }
170
+
171
+ .u-im-chat-box__tools {
172
+ padding: 16rpx 32rpx;
173
+ border-bottom: 2rpx solid #e4e7ed;
174
+ }
175
+
176
+ .u-im-chat-box__textarea {
177
+ padding: 24rpx 32rpx;
178
+ }
179
+
180
+ .chat-textarea {
181
+ width: 100%;
182
+ min-height: 80rpx;
183
+ padding: 16rpx;
184
+ border: 2rpx solid #dcdfe6;
185
+ border-radius: 8rpx;
186
+ font-size: 28rpx;
187
+ background-color: #fff;
188
+ }
189
+
190
+ .u-im-chat-box__send {
191
+ padding: 0 32rpx 24rpx;
192
+ text-align: right;
193
+ }
194
+
195
+ .send-button {
196
+ background-color: #409EFF;
197
+ color: #fff;
198
+ border: none;
199
+ border-radius: 8rpx;
200
+ padding: 16rpx 32rpx;
201
+ font-size: 28rpx;
202
+ }
203
+ </style>
@@ -0,0 +1,185 @@
1
+ <template>
2
+ <view class="u-im-chat-item" :class="[`u-im-chat-item--${type}`]" @click="handleClick">
3
+ <view class="u-im-chat-item__avatar">
4
+ <!-- 替换 u-avatar -->
5
+ <view class="avatar-fallback">
6
+ <image v-if="avatar" :src="avatar" class="avatar-image" mode="aspectFill" />
7
+ <text v-else class="avatar-text">{{ displayName }}</text>
8
+ </view>
9
+ </view>
10
+ <view class="u-im-chat-item__content">
11
+ <view class="u-im-chat-item__header">
12
+ <text class="u-im-chat-item__name">{{ name }}</text>
13
+ <text class="u-im-chat-item__time">{{ time }}</text>
14
+ </view>
15
+ <view class="u-im-chat-item__message">
16
+ <text class="u-im-chat-item__text">{{ lastMessage }}</text>
17
+ <!-- 替换 u-badge -->
18
+ <view v-if="unreadCount > 0" class="badge-fallback">
19
+ <text class="badge-text">{{ displayUnreadCount }}</text>
20
+ </view>
21
+ </view>
22
+ </view>
23
+ </view>
24
+ </template>
25
+
26
+ <script>
27
+ export default {
28
+ name: 'ChatItem',
29
+ props: {
30
+ type: {
31
+ type: String,
32
+ default: 'default',
33
+ validator: function (value) {
34
+ return ['default', 'group'].includes(value)
35
+ }
36
+ },
37
+ avatar: {
38
+ type: String,
39
+ default: ''
40
+ },
41
+ name: {
42
+ type: String,
43
+ required: true
44
+ },
45
+ time: {
46
+ type: String,
47
+ required: true
48
+ },
49
+ lastMessage: {
50
+ type: String,
51
+ required: true
52
+ },
53
+ unreadCount: {
54
+ type: Number,
55
+ default: 0
56
+ }
57
+ },
58
+ computed: {
59
+ displayName() {
60
+ return this.name ? this.name.charAt(0) : ''
61
+ },
62
+ displayUnreadCount() {
63
+ return this.unreadCount > 99 ? '99+' : this.unreadCount
64
+ }
65
+ },
66
+ methods: {
67
+ handleClick() {
68
+ this.showToast('恭喜发财')
69
+ this.$emit('click')
70
+ },
71
+ showToast(message) {
72
+ uni.showToast({
73
+ title: message,
74
+ icon: 'none'
75
+ })
76
+ },
77
+ }
78
+ }
79
+ </script>
80
+
81
+ <style scoped>
82
+ .u-im-chat-item {
83
+ display: flex;
84
+ padding: 24rpx 32rpx;
85
+ transition: background-color 0.3s;
86
+ border-bottom: 2rpx solid #f5f7fa;
87
+ }
88
+
89
+ .u-im-chat-item:active {
90
+ background-color: #f5f7fa;
91
+ }
92
+
93
+ .u-im-chat-item__avatar {
94
+ margin-right: 24rpx;
95
+ }
96
+
97
+ .avatar-fallback {
98
+ width: 80rpx;
99
+ height: 80rpx;
100
+ border-radius: 50%;
101
+ background-color: #409EFF;
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ overflow: hidden;
106
+ }
107
+
108
+ .avatar-image {
109
+ width: 100%;
110
+ height: 100%;
111
+ }
112
+
113
+ .avatar-text {
114
+ color: white;
115
+ font-size: 32rpx;
116
+ font-weight: bold;
117
+ }
118
+
119
+ .u-im-chat-item__content {
120
+ flex: 1;
121
+ min-width: 0;
122
+ }
123
+
124
+ .u-im-chat-item__header {
125
+ display: flex;
126
+ justify-content: space-between;
127
+ align-items: center;
128
+ margin-bottom: 8rpx;
129
+ }
130
+
131
+ .u-im-chat-item__name {
132
+ font-size: 32rpx;
133
+ font-weight: 500;
134
+ color: #303133;
135
+ overflow: hidden;
136
+ text-overflow: ellipsis;
137
+ white-space: nowrap;
138
+ flex: 1;
139
+ }
140
+
141
+ .u-im-chat-item__time {
142
+ font-size: 24rpx;
143
+ color: #909399;
144
+ flex-shrink: 0;
145
+ margin-left: 16rpx;
146
+ }
147
+
148
+ .u-im-chat-item__message {
149
+ display: flex;
150
+ justify-content: space-between;
151
+ align-items: center;
152
+ }
153
+
154
+ .u-im-chat-item__text {
155
+ font-size: 28rpx;
156
+ color: #606266;
157
+ overflow: hidden;
158
+ text-overflow: ellipsis;
159
+ white-space: nowrap;
160
+ flex: 1;
161
+ }
162
+
163
+ .badge-fallback {
164
+ background-color: #FA3534;
165
+ border-radius: 40rpx;
166
+ min-width: 36rpx;
167
+ height: 36rpx;
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ margin-left: 16rpx;
172
+ }
173
+
174
+ .badge-text {
175
+ color: white;
176
+ font-size: 20rpx;
177
+ font-weight: bold;
178
+ padding: 0 8rpx;
179
+ }
180
+
181
+ /* 群聊样式 */
182
+ .u-im-chat-item--group .u-im-chat-item__name::before {
183
+ content: "👥 ";
184
+ }
185
+ </style>
@@ -0,0 +1,205 @@
1
+ <template>
2
+ <view class="u-im-message-item" :class="[`u-im-message-item--${position}`]">
3
+ <view class="u-im-message-item__avatar" v-if="showAvatar">
4
+ <!-- 替换 u-avatar -->
5
+ <view class="avatar-fallback">
6
+ <image v-if="avatar" :src="avatar" class="avatar-image" mode="aspectFill" />
7
+ <text v-else class="avatar-text">U</text>
8
+ </view>
9
+ </view>
10
+ <view class="u-im-message-item__content">
11
+ <view class="u-im-message-item__bubble" :class="[`u-im-message-item__bubble--${type}`]">
12
+ <text v-if="type === 'text'" class="u-im-message-item__text">
13
+ {{ content }}
14
+ </text>
15
+ <view v-else-if="type === 'image'" class="u-im-message-item__image">
16
+ <!-- 替换 u-image -->
17
+ <image :src="content" class="image-fallback" mode="aspectFill" />
18
+ </view>
19
+ <view v-else-if="type === 'voice'" class="u-im-message-item__voice">
20
+ <!-- 替换 u-icon -->
21
+ <text class="voice-icon">▶</text>
22
+ <text class="u-im-message-item__duration">{{ duration }}''</text>
23
+ </view>
24
+ </view>
25
+ <view class="u-im-message-item__status" v-if="position === 'right'">
26
+ <!-- 替换 u-icon -->
27
+ <text v-if="status === 'sending'" class="status-icon sending">⏳</text>
28
+ <text v-else-if="status === 'success'" class="status-icon success">✓</text>
29
+ <text v-else-if="status === 'failed'" class="status-icon failed">✗</text>
30
+ </view>
31
+ </view>
32
+ </view>
33
+ </template>
34
+
35
+ <script>
36
+ export default {
37
+ name: 'ChatMessageItem',
38
+ props: {
39
+ position: {
40
+ type: String,
41
+ default: 'left',
42
+ validator: function (value) {
43
+ return ['left', 'right'].includes(value)
44
+ }
45
+ },
46
+ type: {
47
+ type: String,
48
+ default: 'text',
49
+ validator: function (value) {
50
+ return ['text', 'image', 'voice', 'file'].includes(value)
51
+ }
52
+ },
53
+ content: {
54
+ type: String,
55
+ required: true
56
+ },
57
+ avatar: {
58
+ type: String,
59
+ default: ''
60
+ },
61
+ showAvatar: {
62
+ type: Boolean,
63
+ default: true
64
+ },
65
+ status: {
66
+ type: String,
67
+ default: 'success',
68
+ validator: function (value) {
69
+ return ['sending', 'success', 'failed'].includes(value)
70
+ }
71
+ },
72
+ duration: {
73
+ type: Number,
74
+ default: 0
75
+ }
76
+ }
77
+ }
78
+ </script>
79
+
80
+ <style scoped>
81
+ .u-im-message-item {
82
+ display: flex;
83
+ margin-bottom: 32rpx;
84
+ }
85
+
86
+ .u-im-message-item--left {
87
+ justify-content: flex-start;
88
+ }
89
+
90
+ .u-im-message-item--right {
91
+ justify-content: flex-end;
92
+ }
93
+
94
+ .u-im-message-item--right .u-im-message-item__content {
95
+ flex-direction: row-reverse;
96
+ }
97
+
98
+ .u-im-message-item__avatar {
99
+ margin: 0 16rpx;
100
+ align-self: flex-end;
101
+ }
102
+
103
+ .avatar-fallback {
104
+ width: 64rpx;
105
+ height: 64rpx;
106
+ border-radius: 50%;
107
+ background-color: #67C23A;
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ overflow: hidden;
112
+ }
113
+
114
+ .avatar-image {
115
+ width: 100%;
116
+ height: 100%;
117
+ }
118
+
119
+ .avatar-text {
120
+ color: white;
121
+ font-size: 24rpx;
122
+ }
123
+
124
+ .u-im-message-item__content {
125
+ display: flex;
126
+ align-items: flex-end;
127
+ max-width: 70%;
128
+ }
129
+
130
+ .u-im-message-item__bubble {
131
+ padding: 16rpx 24rpx;
132
+ border-radius: 16rpx;
133
+ position: relative;
134
+ max-width: 100%;
135
+ }
136
+
137
+ .u-im-message-item__bubble--text {
138
+ background-color: #f0f2f5;
139
+ color: #303133;
140
+ }
141
+
142
+ .u-im-message-item--right .u-im-message-item__bubble--text {
143
+ background-color: #409eff;
144
+ color: #fff;
145
+ }
146
+
147
+ .u-im-message-item__image {
148
+ border-radius: 8rpx;
149
+ overflow: hidden;
150
+ }
151
+
152
+ .image-fallback {
153
+ width: 400rpx;
154
+ height: 300rpx;
155
+ }
156
+
157
+ .u-im-message-item__voice {
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 16rpx;
161
+ padding: 16rpx 32rpx;
162
+ background-color: #f0f2f5;
163
+ border-radius: 32rpx;
164
+ }
165
+
166
+ .u-im-message-item--right .u-im-message-item__voice {
167
+ background-color: #409eff;
168
+ color: #fff;
169
+ }
170
+
171
+ .u-im-message-item__text {
172
+ word-break: break-word;
173
+ line-height: 1.4;
174
+ }
175
+
176
+ .voice-icon {
177
+ font-size: 32rpx;
178
+ }
179
+
180
+ .u-im-message-item__duration {
181
+ font-size: 24rpx;
182
+ }
183
+
184
+ .u-im-message-item__status {
185
+ margin: 0 8rpx;
186
+ display: flex;
187
+ align-items: center;
188
+ }
189
+
190
+ .status-icon {
191
+ font-size: 28rpx;
192
+ }
193
+
194
+ .status-icon.sending {
195
+ color: #909399;
196
+ }
197
+
198
+ .status-icon.success {
199
+ color: #67C23A;
200
+ }
201
+
202
+ .status-icon.failed {
203
+ color: #F56C6C;
204
+ }
205
+ </style>
package/src/index.js ADDED
@@ -0,0 +1,31 @@
1
+ import ChatItem from './components/chat-item/index.vue'
2
+ import ChatMessageItem from './components/chat-message-item/index.vue'
3
+ import ChatBox from './components/chat-box/index.vue'
4
+
5
+ // 重要:为组件添加名称,以支持开发环境
6
+ ChatItem.name = 'ChatItem'
7
+ ChatMessageItem.name = 'ChatMessageItem'
8
+ ChatBox.name = 'ChatBox'
9
+
10
+ const components = [
11
+ ChatItem,
12
+ ChatMessageItem,
13
+ ChatBox
14
+ ]
15
+
16
+ const install = (app) => {
17
+ components.forEach(component => {
18
+ app.component(component.name || '', component)
19
+ })
20
+ }
21
+
22
+ export {
23
+ ChatItem,
24
+ ChatMessageItem,
25
+ ChatBox,
26
+ install
27
+ }
28
+
29
+ export default {
30
+ install
31
+ }