Commit d85beb14 d85beb145cadf3ec5f3212bd3092c80c35157bbd by yangjun@hikoon.cn

demo

1 parent 7e3e473c
Showing 159 changed files with 423 additions and 2575 deletions
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 "tweblive": "^1.1.1", 22 "tweblive": "^1.1.1",
23 "vue": "^2.6.11", 23 "vue": "^2.6.11",
24 "vue-clipboard2": "^0.3.1", 24 "vue-clipboard2": "^0.3.1",
25 "vue-infinite-scroll": "^2.0.2",
25 "vuex": "^3.1.2" 26 "vuex": "^3.1.2"
26 }, 27 },
27 "devDependencies": { 28 "devDependencies": {
......
1 <template> 1 <template>
2 <div class="avatar" :class="shape === 'circle' ? 'shape-circle' : ''"> 2 <div class="avatar" :class="shape === 'circle' ? 'shape-circle' : ''">
3 <img :src="avatarSrc"> 3 <img alt="头像" :src="avatarSrc">
4 </div> 4 </div>
5 </template> 5 </template>
6 6
7 <script> 7 <script>
8 import systemAvatar from '@/assets/image/system.png' 8 import systemAvatar from '@/assets/image/system.png'
9
9 export default { 10 export default {
10 props: { 11 props: {
11 src: String, 12 src: String,
...@@ -28,7 +29,7 @@ export default { ...@@ -28,7 +29,7 @@ export default {
28 } 29 }
29 }, 30 },
30 defaultSrc: function () { 31 defaultSrc: function () {
31 switch(this.type) { 32 switch (this.type) {
32 case 'C2C': 33 case 'C2C':
33 // 个人头像 34 // 个人头像
34 return 'https://imgcache.qq.com/open/qcloud/video/act/webim-avatar/avatar-2.png' 35 return 'https://imgcache.qq.com/open/qcloud/video/act/webim-avatar/avatar-2.png'
...@@ -53,9 +54,11 @@ export default { ...@@ -53,9 +54,11 @@ export default {
53 width 100% 54 width 100%
54 height 100% 55 height 100%
55 overflow hidden 56 overflow hidden
57
56 img 58 img
57 width 100% 59 width 100%
58 height 100% 60 height 100%
61
59 .shape-circle 62 .shape-circle
60 border-radius 50% 63 border-radius 50%
61 </style> 64 </style>
......
...@@ -8,18 +8,18 @@ ...@@ -8,18 +8,18 @@
8 <span class="tim-icon-close" title="删除会话" @click="deleteConversation"></span> 8 <span class="tim-icon-close" title="删除会话" @click="deleteConversation"></span>
9 </div> 9 </div>
10 <div class="warp"> 10 <div class="warp">
11 <avatar :src="avatar" :type="conversation.type" /> 11 <avatar :src="avatar" :type="conversation.type"/>
12 <div class="content"> 12 <div class="content">
13 <div class="row-1"> 13 <div class="row-1">
14 <div class="name"> 14 <div class="name">
15 <div class="text-ellipsis"> 15 <div class="text-ellipsis">
16 <span :title="conversation.userProfile.nick || conversation.userProfile.userID" 16 <span :title="conversation.userProfile.nick || conversation.userProfile.userID"
17 v-if="conversation.type === TIM.TYPES.CONV_C2C" 17 v-if="conversation.type === TIM.TYPES.CONV_C2C"
18 >{{conversation.userProfile.nick || conversation.userProfile.userID}} 18 >{{ conversation.userProfile.nick || conversation.userProfile.userID }}
19 </span> 19 </span>
20 <span :title="conversation.groupProfile.name || conversation.groupProfile.groupID" 20 <span :title="conversation.groupProfile.name || conversation.groupProfile.groupID"
21 v-else-if="conversation.type === TIM.TYPES.CONV_GROUP" 21 v-else-if="conversation.type === TIM.TYPES.CONV_GROUP"
22 >{{conversation.groupProfile.name || conversation.groupProfile.groupID}} 22 >{{ conversation.groupProfile.name || conversation.groupProfile.groupID }}
23 </span> 23 </span>
24 <span 24 <span
25 v-else-if="conversation.type === TIM.TYPES.CONV_SYSTEM" 25 v-else-if="conversation.type === TIM.TYPES.CONV_SYSTEM"
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
29 </div> 29 </div>
30 <div class="unread-count"> 30 <div class="unread-count">
31 <span class="badge" v-if="showUnreadCount"> 31 <span class="badge" v-if="showUnreadCount">
32 {{conversation.unreadCount > 99 ? '99+' : conversation.unreadCount}} 32 {{ conversation.unreadCount > 99 ? '99+' : conversation.unreadCount }}
33 </span> 33 </span>
34 </div> 34 </div>
35 </div> 35 </div>
...@@ -37,13 +37,17 @@ ...@@ -37,13 +37,17 @@
37 <div class="summary"> 37 <div class="summary">
38 <div v-if="conversation.lastMessage" class="text-ellipsis"> 38 <div v-if="conversation.lastMessage" class="text-ellipsis">
39 <span class="remind" style="color:red;" v-if="hasMessageAtMe">[有人提到我]</span> 39 <span class="remind" style="color:red;" v-if="hasMessageAtMe">[有人提到我]</span>
40 <span class="text" :title="conversation.lastMessage.messageForShow"> 40 <span class="text" title="图片"
41 {{messageForShow}} 41 v-if="conversation.lastMessage.type === 'TIMCustomElem' && conversation.lastMessage.payload.data === 'image'">
42 [图片]
43 </span>
44 <span v-else class="text" :title="conversation.lastMessage.messageForShow">
45 {{ messageForShow }}
42 </span> 46 </span>
43 </div> 47 </div>
44 </div> 48 </div>
45 <div class="date"> 49 <div class="date">
46 {{date}} 50 {{ date }}
47 </div> 51 </div>
48 </div> 52 </div>
49 </div> 53 </div>
...@@ -53,11 +57,13 @@ ...@@ -53,11 +57,13 @@
53 </template> 57 </template>
54 58
55 <script> 59 <script>
56 import { mapGetters, mapState } from 'vuex' 60 import {mapGetters, mapState} from 'vuex'
57 import { isToday, getDate, getTime } from '../../utils/date' 61 import {getDate, getTime, isToday} from '../../utils/date'
62
58 export default { 63 export default {
59 name: 'conversation-item', 64 name: 'conversation-item',
60 props: ['conversation'], 65 props: ['conversation'],
66 filters: {},
61 data() { 67 data() {
62 return { 68 return {
63 popoverVisible: false, 69 popoverVisible: false,
...@@ -88,7 +94,7 @@ export default { ...@@ -88,7 +94,7 @@ export default {
88 } 94 }
89 return getDate(date) 95 return getDate(date)
90 }, 96 },
91 avatar: function() { 97 avatar: function () {
92 switch (this.conversation.type) { 98 switch (this.conversation.type) {
93 case 'GROUP': 99 case 'GROUP':
94 return this.conversation.groupProfile.avatar 100 return this.conversation.groupProfile.avatar
...@@ -98,7 +104,7 @@ export default { ...@@ -98,7 +104,7 @@ export default {
98 return '' 104 return ''
99 } 105 }
100 }, 106 },
101 conversationName: function() { 107 conversationName: function () {
102 if (this.conversation.type === this.TIM.TYPES.CONV_C2C) { 108 if (this.conversation.type === this.TIM.TYPES.CONV_C2C) {
103 return this.conversation.userProfile.nick || this.conversation.userProfile.userID 109 return this.conversation.userProfile.nick || this.conversation.userProfile.userID
104 } 110 }
...@@ -203,42 +209,53 @@ export default { ...@@ -203,42 +209,53 @@ export default {
203 transition .2s 209 transition .2s
204 // &:first-child 210 // &:first-child
205 // padding-top 30px 211 // padding-top 30px
212
206 &:hover 213 &:hover
207 background-color $background 214 background-color $background
215
208 .close-btn 216 .close-btn
209 right 3px 217 right 3px
218
210 .close-btn 219 .close-btn
211 position absolute 220 position absolute
212 right -20px 221 right -20px
213 top 3px 222 top 3px
214 color $font-dark 223 color $font-dark
215 transition: all .2s ease; 224 transition: all .2s ease;
225
216 &:hover 226 &:hover
217 color $danger 227 color $danger
228
218 .warp 229 .warp
219 display flex 230 display flex
231
220 .avatar 232 .avatar
221 width 40px 233 width 40px
222 height 40px 234 height 40px
223 margin-right 10px 235 margin-right 10px
224 border-radius 50% 236 border-radius 50%
225 flex-shrink 0 237 flex-shrink 0
238
226 .content 239 .content
227 flex 1 240 flex 1
228 height 40px 241 height 40px
229 overflow hidden 242 overflow hidden
243
230 .row-1 244 .row-1
231 display flex 245 display flex
232 line-height 21px 246 line-height 21px
247
233 .name 248 .name
234 color $font-light 249 color $font-light
235 flex 1 250 flex 1
236 min-width 0px 251 min-width 0px
252
237 .unread-count 253 .unread-count
238 padding-left 10px 254 padding-left 10px
239 flex-shrink 0 255 flex-shrink 0
240 color $font-dark 256 color $font-dark
241 font-size 12px 257 font-size 12px
258
242 .badge 259 .badge
243 vertical-align bottom 260 vertical-align bottom
244 background-color $danger 261 background-color $danger
...@@ -252,25 +269,31 @@ export default { ...@@ -252,25 +269,31 @@ export default {
252 padding 0 6px 269 padding 0 6px
253 text-align center 270 text-align center
254 white-space nowrap 271 white-space nowrap
272
255 .row-2 273 .row-2
256 display flex 274 display flex
257 font-size 12px 275 font-size 12px
258 padding-top 3px 276 padding-top 3px
277
259 .summary 278 .summary
260 flex 1 279 flex 1
261 overflow hidden 280 overflow hidden
262 min-width 0px 281 min-width 0px
263 color: $secondary 282 color: $secondary
283
264 .remind 284 .remind
265 color $danger 285 color $danger
286
266 .date 287 .date
267 padding-left 10px 288 padding-left 10px
268 flex-shrink 0 289 flex-shrink 0
269 text-align right 290 text-align right
270 color $font-dark 291 color $font-dark
292
271 .choose { 293 .choose {
272 background-color: $background; 294 background-color: $background;
273 } 295 }
296
274 .context-menu-button { 297 .context-menu-button {
275 padding: 10px 298 padding: 10px
276 border: 2px solid $primary; 299 border: 2px solid $primary;
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
4 <button title="刷新列表" @click="handleRefresh"> 4 <button title="刷新列表" @click="handleRefresh">
5 <i class="tim-icon-refresh"></i> 5 <i class="tim-icon-refresh"></i>
6 </button> 6 </button>
7 <button title="创建会话" @click="handleAddButtonClick"> 7 <!-- <button title="创建会话" @click="handleAddButtonClick">-->
8 <i class="tim-icon-add"></i> 8 <!-- <i class="tim-icon-add"></i>-->
9 </button> 9 <!-- </button>-->
10 </div> 10 </div>
11 <div class="scroll-container"> 11 <div class="scroll-container">
12 <conversation-item 12 <conversation-item
...@@ -31,7 +31,7 @@ import {mapState} from 'vuex' ...@@ -31,7 +31,7 @@ import {mapState} from 'vuex'
31 31
32 export default { 32 export default {
33 name: 'ConversationList', 33 name: 'ConversationList',
34 components: { ConversationItem }, 34 components: {ConversationItem},
35 data() { 35 data() {
36 return { 36 return {
37 showDialog: false, 37 showDialog: false,
...@@ -60,7 +60,7 @@ export default { ...@@ -60,7 +60,7 @@ export default {
60 let that = this 60 let that = this
61 return function () { 61 return function () {
62 if (!that.timeout) { 62 if (!that.timeout) {
63 that.timeout = setTimeout(() =>{ 63 that.timeout = setTimeout(() => {
64 that.timeout = null 64 that.timeout = null
65 that.tim.getConversationList().then(() => { 65 that.tim.getConversationList().then(() => {
66 that.$store.commit('showMessage', { 66 that.$store.commit('showMessage', {
...@@ -150,11 +150,13 @@ export default { ...@@ -150,11 +150,13 @@ export default {
150 width 100% 150 width 100%
151 display flex 151 display flex
152 flex-direction column // -reverse 152 flex-direction column // -reverse
153
153 .header-bar 154 .header-bar
154 flex-shrink 0 155 flex-shrink 0
155 height 50px 156 height 50px
156 border-bottom 1px solid $background-deep-dark 157 border-bottom 1px solid $background-deep-dark
157 padding 10px 10px 10px 20px 158 padding 10px 10px 10px 20px
159
158 button 160 button
159 float right 161 float right
160 display: inline-block; 162 display: inline-block;
...@@ -177,14 +179,17 @@ export default { ...@@ -177,14 +179,17 @@ export default {
177 white-space: nowrap; 179 white-space: nowrap;
178 border-radius: 50% 180 border-radius: 50%
179 outline 0 181 outline 0
182
180 &:hover 183 &:hover
181 // background $light-primary 184 // background $light-primary
182 // color $white 185 // color $white
183 transform: rotate(360deg); 186 transform: rotate(360deg);
184 color $light-primary 187 color $light-primary
188
185 .scroll-container 189 .scroll-container
186 overflow-y scroll 190 overflow-y scroll
187 flex 1 191 flex 1
192
188 .bottom-circle-btn { 193 .bottom-circle-btn {
189 position: absolute; 194 position: absolute;
190 bottom: 20px; 195 bottom: 20px;
......
1 <template> 1 <template>
2 <div class="profile-user"> 2 <div class="profile-user">
3 <avatar :title=userProfile.userID :src="userProfile.avatar" /> 3 <avatar :title=userProfile.userID :src="userProfile.avatar"/>
4 <div class="nick-name text-ellipsis"> 4 <div class="nick-name text-ellipsis">
5 <span v-if="userProfile.nick" :title=userProfile.nick> 5 <span v-if="userProfile.nick" :title=userProfile.nick>
6 {{ userProfile.nick }} 6 {{ userProfile.nick }}
...@@ -12,21 +12,25 @@ ...@@ -12,21 +12,25 @@
12 <div class="gender" v-if="genderClass"> 12 <div class="gender" v-if="genderClass">
13 <span :title="gender" class="iconfont" :class="genderClass"></span> 13 <span :title="gender" class="iconfont" :class="genderClass"></span>
14 </div> 14 </div>
15 <el-button 15 <div>
16 title="将该用户加入黑名单" 16 <span>{{ userProfile.selfSignature }}</span>
17 type="text" 17 </div>
18 @click="addToBlackList" 18 <!-- <el-button-->
19 v-if="!isInBlacklist && userProfile.userID !== myUserID" 19 <!-- title="将该用户加入黑名单"-->
20 class="btn-add-blacklist" 20 <!-- type="text"-->
21 >加入黑名单</el-button 21 <!-- @click="addToBlackList"-->
22 > 22 <!-- v-if="!isInBlacklist && userProfile.userID !== myUserID"-->
23 <el-button title="将该用户移出黑名单" type="text" @click="removeFromBlacklist" v-else-if="isInBlacklist">移出黑名单</el-button> 23 <!-- class="btn-add-blacklist"-->
24 <!-- >加入黑名单</el-button-->
25 <!-- >-->
26 <!-- <el-button title="将该用户移出黑名单" type="text" @click="removeFromBlacklist" v-else-if="isInBlacklist">移出黑名单</el-button>-->
24 <!-- 拉黑 和 反拉黑 --> 27 <!-- 拉黑 和 反拉黑 -->
25 </div> 28 </div>
26 </template> 29 </template>
27 30
28 <script> 31 <script>
29 import { mapState } from 'vuex' 32 import {mapState} from 'vuex'
33
30 export default { 34 export default {
31 props: { 35 props: {
32 userProfile: { 36 userProfile: {
...@@ -66,7 +70,7 @@ export default { ...@@ -66,7 +70,7 @@ export default {
66 methods: { 70 methods: {
67 addToBlackList() { 71 addToBlackList() {
68 this.tim 72 this.tim
69 .addToBlacklist({ userIDList: [this.userProfile.userID] }) 73 .addToBlacklist({userIDList: [this.userProfile.userID]})
70 .then(() => { 74 .then(() => {
71 this.$store.dispatch('getBlacklist') 75 this.$store.dispatch('getBlacklist')
72 }) 76 })
...@@ -78,7 +82,7 @@ export default { ...@@ -78,7 +82,7 @@ export default {
78 }) 82 })
79 }, 83 },
80 removeFromBlacklist() { 84 removeFromBlacklist() {
81 this.tim.removeFromBlacklist({ userIDList: [this.userProfile.userID] }).then(() => { 85 this.tim.removeFromBlacklist({userIDList: [this.userProfile.userID]}).then(() => {
82 this.$store.commit('removeFromBlacklist', this.userProfile.userID) 86 this.$store.commit('removeFromBlacklist', this.userProfile.userID)
83 }) 87 })
84 .catch(error => { 88 .catch(error => {
...@@ -97,23 +101,28 @@ export default { ...@@ -97,23 +101,28 @@ export default {
97 width 100% 101 width 100%
98 text-align center 102 text-align center
99 padding 0 20px 103 padding 0 20px
104
100 .avatar 105 .avatar
101 width 160px 106 width 160px
102 height 160px 107 height 160px
103 border-radius 50% 108 border-radius 50%
104 margin 30px auto 109 margin 30px auto
110
105 .nick-name 111 .nick-name
106 width 100% 112 width 100%
107 color $base 113 color $base
108 font-size 20px 114 font-size 20px
109 font-weight bold 115 font-weight bold
110 text-shadow $font-dark 0 0 0.1em 116 text-shadow $font-dark 0 0 0.1em
117
111 .anonymous 118 .anonymous
112 color $first 119 color $first
113 text-shadow none 120 text-shadow none
121
114 .gender 122 .gender
115 padding 5px 0 10px 0 123 padding 5px 0 10px 0
116 border-bottom 1px solid $border-base 124 border-bottom 1px solid $border-base
125
117 .btn-add-blacklist 126 .btn-add-blacklist
118 color $danger 127 color $danger
119 </style> 128 </style>
......
1 <template> 1 <template>
2 <div> 2 <div class="friend-item-container" @click="handleFriendClick">
3 <el-row class="friend-item-container"> 3 <el-row class="friend-list" type="flex" align="middle" justify="center" :gutter="16">
4 <el-col :span="6"> 4 <el-col :span="6">
5 <avatar :src="friend.profile.avatar"/> 5 <avatar class="friend-avatar" :src="friend.avatar"/>
6 </el-col> 6 </el-col>
7 <el-col :span="18"> 7 <el-col :span="18">
8 <div class="friend-name">{{ friend.profile.nick || friend.userID }}</div> 8 <div class="friend-name">{{ friend.name }}</div>
9 </el-col> 9 </el-col>
10 </el-row> 10 </el-row>
11 </div> 11 </div>
...@@ -21,18 +21,32 @@ export default { ...@@ -21,18 +21,32 @@ export default {
21 }, 21 },
22 methods: { 22 methods: {
23 handleFriendClick() { 23 handleFriendClick() {
24 this.tim.getConversationProfile(`C2C${this.friend.userID}`) 24 this.tim.getConversationProfile(`C2C${this.friend.esm_id}`)
25 .then(({data}) => this.$store.commit('updateCurrentConversation', data)) 25 .then(({data}) => {
26 .catch(error => { 26 console.log(data)
27 this.$store.commit('showMessage', { 27 this.$store.commit('updateCurrentConversation', data)
28 type: 'error', 28 this.$store.commit('setActiveMenu', 'conversation-list')
29 message: error.message 29 this.$store.dispatch('checkoutConversation', data.conversation.conversationID)
30 })
31 }) 30 })
31 .catch(error => this.$store.commit('showMessage', {type: 'error', message: error.message}))
32 } 32 }
33 } 33 }
34 } 34 }
35 </script> 35 </script>
36 36
37 <style lang="stylus" scoped> 37 <style lang="stylus" scoped>
38 .friend-item-container
39 color #f7f7f8
40
41 :hover
42 background-color #404953
43 cursor pointer
44
45 .friend-list
46 padding 10px 15px
47
48 .friend-avatar
49 height 48px
50 width 48px
51
38 </style> 52 </style>
......
1 <template> 1 <template>
2 <!-- <div class="friend-list-container" :class="{'default': !hasFriend}">-->
3 <div class="list-container"> 2 <div class="list-container">
4 3 <div class="header-bar">
4 <el-input v-model="select" size="mini" placeholder="筛选昵称" prefix-icon="el-icon-search"/>
5 </div>
5 <el-collapse v-model="activeNames" class="friend-list-container"> 6 <el-collapse v-model="activeNames" class="friend-list-container">
6 <el-collapse-item title="用户组" name="user"> 7 <el-collapse-item title="用户组" name="user">
7 <friend-item v-for="friend in friendList" :key="friend.userID" :friend="friend"/> 8 <friend-item v-for="friend in userList" :key="friend.ems_id" :friend="friend"/>
8 </el-collapse-item> 9 </el-collapse-item>
9 <el-collapse-item title="策划组" name="scheme"> 10 <el-collapse-item title="策划组" name="scheme">
10 11 <friend-item v-for="friend in schemeList" :key="friend.ems_id" :friend="friend"/>
11 </el-collapse-item> 12 </el-collapse-item>
12 <el-collapse-item title="管理组" name="admin"> 13 <el-collapse-item title="管理组" name="admin">
13 14 <friend-item v-for="friend in adminList" :key="friend.ems_id" :friend="friend"/>
14 </el-collapse-item> 15 </el-collapse-item>
15 </el-collapse> 16 </el-collapse>
16 </div> 17 </div>
17 <!-- <div v-if="hasFriend">-->
18 <!-- <friend-item v-for="friend in friendList" :key="friend.userID" :friend="friend"/>-->
19 <!-- </div>-->
20 <!-- <div style="color:gray;" v-else>暂无数据</div>-->
21 <!-- </div>-->
22 </template> 18 </template>
23 19
24 <script> 20 <script>
...@@ -32,21 +28,32 @@ export default { ...@@ -32,21 +28,32 @@ export default {
32 }, 28 },
33 computed: { 29 computed: {
34 ...mapState({ 30 ...mapState({
35 friendList: state => state.friend.friendList 31 friendList: state => state.friend.friendList,
36 }), 32 adminList(state) {
37 hasFriend() { 33 const list = state.friend.adminList || []
38 return this.friendList.length > 0 34 return this.select.length === 0 ? list : list.filter(item => item.name.indexOf(this.select) > -1)
35 },
36 userList(state) {
37 const list = state.friend.userList || []
38 return this.select.length === 0 ? list : list.filter(item => item.name.indexOf(this.select) > -1)
39 },
40 schemeList(state) {
41 const list = state.friend.schemeList || []
42 return this.select.length === 0 ? list : list.filter(item => item.name.indexOf(this.select) > -1)
39 } 43 }
44 }),
40 }, 45 },
41 data() { 46 data() {
42 return { 47 return {
43 activeNames: [], 48 activeNames: [],
49 select: ''
44 } 50 }
45 } 51 },
52 methods: {}
46 } 53 }
47 </script> 54 </script>
48 55
49 <style lang="stylus" scpoed> 56 <style lang="stylus" scoped>
50 .list-container 57 .list-container
51 height 100% 58 height 100%
52 width 100% 59 width 100%
...@@ -54,16 +61,53 @@ export default { ...@@ -54,16 +61,53 @@ export default {
54 flex-direction column 61 flex-direction column
55 62
56 .friend-list-container 63 .friend-list-container
57 margin 1px 64 border-top: unset
58 border-top:unset
59 border-bottom unset 65 border-bottom unset
66 padding 0 15px
67 overflow-y: scroll
68 height: 100%
69
70 >>> .el-collapse-item
71 justify-content: center
72 align-items: center
60 73
74 .el-collapse-item__header
75 background-color transparent !important
76 border-bottom: unset
77 color #f7f7f8
61 78
62 .default { 79 .el-collapse-item__wrap
80 background-color transparent !important
81 border-bottom: unset
82
83 .el-collapse-item__content
84 padding-bottom 0
85
86 .header-bar
63 display: flex; 87 display: flex;
64 justify-content: center; 88 flex-shrink 0
65 align-items: center; 89 height 50px
66 height: 100%; 90 border-bottom 1px solid $background-deep-dark
67 overflow-y: scroll; 91 padding 10px 10px 10px 20px
68 } 92
93 >>> .el-input
94 width 100%
95 margin-right 10px
96
97 input
98 color $first
99 border none
100 border-radius 30px
101 background-color $deep-background !important
102
103 &::placeholder
104 color $font-dark
105
106 .el-icon-search
107 color $font-dark
108
109 &:hover
110 transform: rotate(360deg);
111 color $light-primary
112
69 </style> 113 </style>
......
1 <template> 1 <template>
2 <div @click="handleGroupClick" class="scroll-container"> 2 <div @click="handleGroupClick" class="scroll-container">
3 <div class="group-item"> 3 <div class="group-item">
4 <avatar :src="group.avatar" /> 4 <avatar :src="group.avatar"/>
5 <div class="group-name text-ellipsis">{{ group.name }}</div> 5 <div class="group-name text-ellipsis">{{ title }}</div>
6 </div> 6 </div>
7 </div> 7 </div>
8 </template> 8 </template>
9 9
10 <script> 10 <script>
11 import {MessageBox} from 'element-ui'
12 import Helper from '../../utils/helper'
13
11 export default { 14 export default {
12 props: ['group'], 15 props: ['group'],
13 data() { 16 data() {
...@@ -21,10 +24,28 @@ export default { ...@@ -21,10 +24,28 @@ export default {
21 ] 24 ]
22 } 25 }
23 }, 26 },
27 computed: {
28 title() {
29 return (this.group.activity_type === 1 ? '推广' : '征集') + ' - ' + this.group.song_name.replace('《', '').replace('》', '')
30 }
31 },
24 methods: { 32 methods: {
25 handleGroupClick() { 33 handleGroupClick() {
26 const conversationID = `GROUP${this.group.groupID}` 34 if (this.group.is_join === 1) {
35 const conversationID = `GROUP${this.group.esm_id}`
27 this.$store.dispatch('checkoutConversation', conversationID) 36 this.$store.dispatch('checkoutConversation', conversationID)
37 } else {
38 MessageBox.confirm('是否加入讨论组:' + this.title, '提示', {
39 type: 'warning', showClose: false
40 }).then(() => {
41 Helper.joinGroup(this.group.id).then(() => {
42 this.group.is_join = 1
43 this.handleGroupClick()
44 })
45 }).catch(() => {
46
47 })
48 }
28 }, 49 },
29 quitGroup() { 50 quitGroup() {
30 this.tim.quitGroup(this.group.groupID) 51 this.tim.quitGroup(this.group.groupID)
...@@ -43,6 +64,7 @@ export default { ...@@ -43,6 +64,7 @@ export default {
43 .scroll-container 64 .scroll-container
44 overflow-y scroll 65 overflow-y scroll
45 flex 1 66 flex 1
67
46 .group-item 68 .group-item
47 display flex 69 display flex
48 padding 10px 20px 70 padding 10px 20px
...@@ -50,14 +72,17 @@ export default { ...@@ -50,14 +72,17 @@ export default {
50 position relative 72 position relative
51 overflow hidden 73 overflow hidden
52 transition .2s 74 transition .2s
75
53 &:hover 76 &:hover
54 background-color $background 77 background-color $background
78
55 .avatar 79 .avatar
56 width 30px 80 width 30px
57 height 30px 81 height 30px
58 border-radius 50% 82 border-radius 50%
59 margin-right 10px 83 margin-right 10px
60 flex-shrink 0 84 flex-shrink 0
85
61 .group-name 86 .group-name
62 flex 1 87 flex 1
63 color $font-light 88 color $font-light
......
1 <template> 1 <template>
2 <div class="list-container"> 2 <div class="list-container"
3 v-loading="hideSearchLoading"
4 element-loading-text="拼命搜索中"
5 element-loading-background="rgba(0, 0, 0, 0.8)">
3 <div class="header-bar"> 6 <div class="header-bar">
4 <el-autocomplete 7 <el-input v-model="search" size="mini" placeholder="筛选群名" prefix-icon="el-icon-search"/>
5 :value-key="'groupID'" 8
6 :debounce="500" 9 <!-- <el-autocomplete-->
7 size="mini" 10 <!-- :value-key="'groupID'"-->
8 v-model="groupID" 11 <!-- :debounce="500"-->
9 placeholder="输入群ID搜索" 12 <!-- size="mini"-->
10 :fetch-suggestions="searchGroupByID" 13 <!-- v-model="groupID"-->
11 class="group-seach-bar" 14 <!-- placeholder="输入群ID搜索"-->
12 prefix-icon="el-icon-search" 15 <!-- :fetch-suggestions="searchGroupByID"-->
13 :hide-loading="hideSearchLoading" 16 <!-- class="group-seach-bar"-->
14 @input="hideSearchLoading = false" 17 <!-- prefix-icon="el-icon-search"-->
15 @select="applyJoinGroup" 18 <!-- :hide-loading="hideSearchLoading"-->
16 ></el-autocomplete> 19 <!-- @input="hideSearchLoading = false"-->
17 <!-- <button title="创建群组" @click="showCreateGroupModel">--> 20 <!-- @select="applyJoinGroup"-->
18 <!-- <i class="tim-icon-add"></i>--> 21 <!-- ></el-autocomplete>-->
19 <!-- </button>--> 22 <!-- <button title="创建群组" @click="showCreateGroupModel">-->
23 <!-- <i class="tim-icon-add"></i>-->
24 <!-- </button>-->
20 </div> 25 </div>
21 <div class="group-container"> 26 <div class="group-container" v-infinite-scroll="fetch" :infinite-scroll-immediate="true"
22 <group-item v-for="group in groupList" :key="group.groupID" :group="group" /> 27 :infinite-scroll-delay="100"
23 <el-dialog title="创建群组" :visible="createGroupModelVisible" @close="closeCreateGroupModel" width="30%"> 28 style="height: calc(80vh - 60px)">
24 <create-group></create-group> 29 <group-item v-for="group in groupList" :key="group.esm_id" :group="group"/>
25 </el-dialog> 30 <!-- <el-dialog title="创建群组" :visible="createGroupModelVisible" @close="closeCreateGroupModel" width="30%">-->
31 <!-- <create-group></create-group>-->
32 <!-- </el-dialog>-->
26 </div> 33 </div>
27 </div> 34 </div>
28 </template> 35 </template>
29 36
30 <script> 37 <script>
31 import { mapState } from 'vuex' 38 import {mapState} from 'vuex'
32 import { Dialog, Autocomplete } from 'element-ui' 39 // import CreateGroup from './create-group.vue'
33 import CreateGroup from './create-group.vue'
34 import GroupItem from './group-item.vue' 40 import GroupItem from './group-item.vue'
41 import Helper from '../../utils/helper'
42
35 export default { 43 export default {
36 data() { 44 data() {
37 return { 45 return {
38 groupID: '', 46 groupID: '',
39 hideSearchLoading: true 47 hideSearchLoading: false,
48 search: '',
49 page: 1,
50 size: 15,
40 } 51 }
41 }, 52 },
42 components: { 53 components: {
43 GroupItem, 54 GroupItem
44 ElDialog: Dialog, 55 // ElDialog: Dialog,
45 CreateGroup, 56 // CreateGroup,
46 ElAutocomplete: Autocomplete 57 // ElAutocomplete: Autocomplete
58 },
59 mounted() {
60
47 }, 61 },
48 computed: { 62 computed: {
49 groupList: function() { 63 groupList: function () {
50 return this.$store.state.group.groupList 64 return this.$store.state.group.groupList
51 }, 65 },
52 ...mapState({ 66 ...mapState({
...@@ -55,11 +69,25 @@ export default { ...@@ -55,11 +69,25 @@ export default {
55 } 69 }
56 }) 70 })
57 }, 71 },
72 created() {
73 this.fetch()
74 },
58 methods: { 75 methods: {
76 fetch() {
77 Helper.groupList({
78 activityNameLike: this.search, size: this.size, page: this.page
79 }).then(res => {
80 this.onGroupUpdated(this.groupList.concat(res.data))
81 ++this.page
82 }).finally(() => {
83 this.hideSearchLoading = false
84 })
85 },
59 onGroupUpdated(groupList) { 86 onGroupUpdated(groupList) {
60 this.$store.dispatch('updateGroupList', groupList) 87 this.$store.dispatch('updateGroupList', groupList)
61 }, 88 },
62 createGroup() {}, 89 createGroup() {
90 },
63 closeCreateGroupModel() { 91 closeCreateGroupModel() {
64 this.$store.commit('updateCreateGroupModelVisible', false) 92 this.$store.commit('updateCreateGroupModelVisible', false)
65 }, 93 },
...@@ -68,7 +96,7 @@ export default { ...@@ -68,7 +96,7 @@ export default {
68 this.hideSearchLoading = false 96 this.hideSearchLoading = false
69 this.tim 97 this.tim
70 .searchGroupByID(queryString) 98 .searchGroupByID(queryString)
71 .then(({ data: { group } }) => { 99 .then(({data: {group}}) => {
72 showInSearchResult([group]) 100 showInSearchResult([group])
73 }) 101 })
74 .catch(() => { 102 .catch(() => {
...@@ -86,9 +114,9 @@ export default { ...@@ -86,9 +114,9 @@ export default {
86 }, 114 },
87 applyJoinGroup(group) { 115 applyJoinGroup(group) {
88 this.tim 116 this.tim
89 .joinGroup({ groupID: group.groupID }) 117 .joinGroup({groupID: group.groupID})
90 .then(async res => { 118 .then(async res => {
91 switch(res.data.status) { 119 switch (res.data.status) {
92 case this.TIM.TYPES.JOIN_STATUS_WAIT_APPROVAL: 120 case this.TIM.TYPES.JOIN_STATUS_WAIT_APPROVAL:
93 this.$store.commit('showMessage', { 121 this.$store.commit('showMessage', {
94 message: '申请成功,等待群管理员确认。', 122 message: '申请成功,等待群管理员确认。',
...@@ -111,7 +139,8 @@ export default { ...@@ -111,7 +139,8 @@ export default {
111 type: 'info' 139 type: 'info'
112 }) 140 })
113 break 141 break
114 default: break 142 default:
143 break
115 } 144 }
116 }) 145 })
117 .catch(error => { 146 .catch(error => {
...@@ -121,6 +150,11 @@ export default { ...@@ -121,6 +150,11 @@ export default {
121 }) 150 })
122 }) 151 })
123 } 152 }
153 },
154 watch: {
155 'search'() {
156 this.fetch()
157 }
124 } 158 }
125 } 159 }
126 </script> 160 </script>
...@@ -131,27 +165,30 @@ export default { ...@@ -131,27 +165,30 @@ export default {
131 width 100% 165 width 100%
132 display flex 166 display flex
133 flex-direction column 167 flex-direction column
168
134 .group-container 169 .group-container
135 overflow-y scroll 170 overflow-y scroll
171
136 .header-bar 172 .header-bar
137 display: flex; 173 display: flex;
138 flex-shrink 0 174 flex-shrink 0
139 height 50px 175 height 50px
140 border-bottom 1px solid $background-deep-dark 176 border-bottom 1px solid $background-deep-dark
141 padding 10px 10px 10px 20px 177 padding 10px 10px 10px 20px
142 .group-seach-bar 178
143 width 100%
144 margin-right 10px
145 >>> .el-input 179 >>> .el-input
146 input 180 input
147 color $first 181 color $first
148 border none 182 border none
149 border-radius 30px 183 border-radius 30px
150 background-color $deep-background !important 184 background-color $deep-background !important
185
151 &::placeholder 186 &::placeholder
152 color $font-dark 187 color $font-dark
188
153 .el-icon-search 189 .el-icon-search
154 color $font-dark 190 color $font-dark
191
155 button 192 button
156 float right 193 float right
157 display: inline-block; 194 display: inline-block;
...@@ -175,9 +212,11 @@ export default { ...@@ -175,9 +212,11 @@ export default {
175 border-radius: 50% 212 border-radius: 50%
176 outline 0 213 outline 0
177 flex-shrink 0 214 flex-shrink 0
215
178 &:hover 216 &:hover
179 transform: rotate(360deg); 217 transform: rotate(360deg);
180 color $light-primary 218 color $light-primary
219
181 .scroll-container 220 .scroll-container
182 overflow-y scroll 221 overflow-y scroll
183 flex 1 222 flex 1
......
...@@ -56,6 +56,7 @@ import ConversationList from '../conversation/conversation-list' ...@@ -56,6 +56,7 @@ import ConversationList from '../conversation/conversation-list'
56 import GroupList from '../group/group-list' 56 import GroupList from '../group/group-list'
57 import FriendList from '../friend/friend-list' 57 import FriendList from '../friend/friend-list'
58 import BlackList from '../blacklist/blacklist' 58 import BlackList from '../blacklist/blacklist'
59 import Helper from '../../utils/helper'
59 60
60 const activeName = { 61 const activeName = {
61 CONVERSATION_LIST: 'conversation-list', 62 CONVERSATION_LIST: 'conversation-list',
...@@ -75,15 +76,12 @@ export default { ...@@ -75,15 +76,12 @@ export default {
75 }, 76 },
76 data() { 77 data() {
77 return { 78 return {
78 active: activeName.CONVERSATION_LIST,
79 activeName: activeName 79 activeName: activeName
80 } 80 }
81 }, 81 },
82 computed: { 82 computed: {
83 ...mapGetters(['totalUnreadCount']), 83 ...mapGetters(['totalUnreadCount']),
84 ...mapState({ 84 ...mapState({userID: state => state.user.userID, active: state => state.activeMenu}),
85 userID: state => state.user.userID,
86 }),
87 showConversationList() { 85 showConversationList() {
88 return this.active === activeName.CONVERSATION_LIST 86 return this.active === activeName.CONVERSATION_LIST
89 }, 87 },
...@@ -104,7 +102,7 @@ export default { ...@@ -104,7 +102,7 @@ export default {
104 }, 102 },
105 methods: { 103 methods: {
106 checkoutActive(name) { 104 checkoutActive(name) {
107 this.active = name 105 this.$store.commit('setActiveMenu', name)
108 }, 106 },
109 handleClick(event) { 107 handleClick(event) {
110 switch (event.target.id) { 108 switch (event.target.id) {
...@@ -129,10 +127,7 @@ export default { ...@@ -129,10 +127,7 @@ export default {
129 switch (this.active) { 127 switch (this.active) {
130 case activeName.CONVERSATION_LIST: 128 case activeName.CONVERSATION_LIST:
131 this.tim.getConversationList().catch(error => { 129 this.tim.getConversationList().catch(error => {
132 this.$store.commit('showMessage', { 130 this.$store.commit('showMessage', {type: 'error', message: error.message})
133 type: 'error',
134 message: error.message
135 })
136 }) 131 })
137 break 132 break
138 case activeName.GROUP_LIST: 133 case activeName.GROUP_LIST:
...@@ -147,36 +142,30 @@ export default { ...@@ -147,36 +142,30 @@ export default {
147 } 142 }
148 }, 143 },
149 getGroupList() { 144 getGroupList() {
150 this.tim 145 Helper.groupList().then(res => this.$store.dispatch('updateGroupList', res.data))
151 .getGroupList() 146 this.tim.getGroupList()
152 .then(({data: groupList}) => { 147 .then(({data: groupList}) => this.$store.dispatch('updateGroupList', groupList))
153 this.$store.dispatch('updateGroupList', groupList) 148 .catch(error => this.$store.commit('showMessage', {type: 'error', message: error.message}))
154 })
155 .catch(error => {
156 this.$store.commit('showMessage', {
157 type: 'error',
158 message: error.message
159 })
160 })
161 }, 149 },
162 getFriendList() { 150 getFriendList() {
163 this.tim 151 Helper.contactList().then(res => this.$store.commit('updateFriendList', res.data))
164 .getFriendList() 152 // this.tim
165 .then(({data: friendList}) => { 153 // .getFriendList()
166 this.$store.commit('upadteFriendList', friendList) 154 // .then(({data: friendList}) => {
167 }) 155 // this.$store.commit('updateFriendList', friendList)
168 .catch(error => { 156 // })
169 this.$store.commit('showMessage', { 157 // .catch(error => {
170 type: 'error', 158 // this.$store.commit('showMessage', {
171 message: error.message 159 // type: 'error',
172 }) 160 // message: error.message
173 }) 161 // })
174 .catch(error => { 162 // })
175 this.$store.commit('showMessage', { 163 // .catch(error => {
176 type: 'error', 164 // this.$store.commit('showMessage', {
177 message: error.message 165 // type: 'error',
178 }) 166 // message: error.message
179 }) 167 // })
168 // })
180 }, 169 },
181 groupLive() { 170 groupLive() {
182 this.$store.commit('updateGroupLiveInfo', { 171 this.$store.commit('updateGroupLiveInfo', {
...@@ -185,7 +174,10 @@ export default { ...@@ -185,7 +174,10 @@ export default {
185 }) 174 })
186 this.$bus.$emit('open-group-live', {channel: 2}) 175 this.$bus.$emit('open-group-live', {channel: 2})
187 }, 176 },
188 } 177 },
178 created() {
179 this.checkoutActive(activeName.CONVERSATION_LIST)
180 },
189 } 181 }
190 </script> 182 </script>
191 183
......
1 <template> 1 <template>
2 <message-bubble :isMine=isMine :message=message> 2 <message-bubble :isMine=isMine :message=message>
3 <div class="custom-element-wrapper"> 3 <div class="custom-element-wrapper">
4 <div class="survey" v-if="this.payload.data === 'survey'"> 4 <div class="survey" v-if="this.payload.data === 'survey'">
5 <div class="title">对IM DEMO的评分和建议</div> 5 <div class="title">对IM DEMO的评分和建议</div>
...@@ -10,23 +10,29 @@ ...@@ -10,23 +10,29 @@
10 text-color="#ff9900" 10 text-color="#ff9900"
11 score-template="{value}"> 11 score-template="{value}">
12 </el-rate> 12 </el-rate>
13 <div class="suggestion">{{this.payload.extension}}</div> 13 <div class="suggestion">{{ this.payload.extension }}</div>
14 </div> 14 </div>
15 <span class="text" title="您可以自行解析自定义消息" v-else> 15 <span class="text" title="您可以自行解析自定义消息" v-else>
16 <template v-if="text.isFromGroupLive && text.isFromGroupLive === 1"> 16 <template v-if="text.isFromGroupLive && text.isFromGroupLive === 1">
17 <message-group-live-status :liveInfo='text' /> 17 <message-group-live-status :liveInfo='text'/>
18 </template> 18 </template>
19 <template v-else>{{text}}</template> 19 <template v-else-if="this.payload.data === 'image'">
20 <el-image :src="this.payload.description" :preview-src-list="[this.payload.description]"/>
21 <!-- <img alt="image" class="image-element" :src="this.payload.description" @load="onImageLoaded"-->
22 <!-- @click="handlePreview"/>-->
23 </template>
24 <template v-else>{{ text }}</template>
20 </span> 25 </span>
21 </div> 26 </div>
22 </message-bubble> 27 </message-bubble>
23 </template> 28 </template>
24 29
25 <script> 30 <script>
26 import { mapState } from 'vuex' 31 import {mapState} from 'vuex'
27 import MessageBubble from '../message-bubble' 32 import MessageBubble from '../message-bubble'
28 import { Rate } from 'element-ui' 33 import {Rate} from 'element-ui'
29 import MessageGroupLiveStatus from '../message-group-live-status' 34 import MessageGroupLiveStatus from '../message-group-live-status'
35 import ImageElement from '../message-elements/image-element.vue'
30 36
31 export default { 37 export default {
32 name: 'CustomElement', 38 name: 'CustomElement',
...@@ -46,7 +52,8 @@ export default { ...@@ -46,7 +52,8 @@ export default {
46 components: { 52 components: {
47 MessageBubble, 53 MessageBubble,
48 ElRate: Rate, 54 ElRate: Rate,
49 MessageGroupLiveStatus 55 MessageGroupLiveStatus,
56 ImageElement,
50 }, 57 },
51 computed: { 58 computed: {
52 ...mapState({ 59 ...mapState({
...@@ -60,11 +67,17 @@ export default { ...@@ -60,11 +67,17 @@ export default {
60 } 67 }
61 }, 68 },
62 methods: { 69 methods: {
70 guid() {
71 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
72 let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8)
73 return v.toString(16)
74 })
75 },
63 translateCustomMessage(payload) { 76 translateCustomMessage(payload) {
64 let videoPayload = {} 77 let videoPayload = {}
65 try{ 78 try {
66 videoPayload = JSON.parse(payload.data) 79 videoPayload = JSON.parse(payload.data)
67 } catch(e) { 80 } catch (e) {
68 videoPayload = {} 81 videoPayload = {}
69 } 82 }
70 if (payload.data === 'group_create') { 83 if (payload.data === 'group_create') {
...@@ -75,29 +88,53 @@ export default { ...@@ -75,29 +88,53 @@ export default {
75 videoPayload.isFromGroupLive = 1 88 videoPayload.isFromGroupLive = 1
76 return videoPayload 89 return videoPayload
77 } 90 }
78 if(payload.text) { 91 if (payload.text) {
79 return payload.text 92 return payload.text
80 }else{ 93 } else {
81 return '[自定义消息]' 94 return '[自定义消息]'
82 } 95 }
96 },
97 formatImageMessage() {
98 console.log(this.message)
99 return {
100 // ID:
101 }
102 },
103 onImageLoaded(event) {
104 console.log(event)
105 this.$bus.$emit('image-loaded', event)
106 },
107 handlePreview() {
108 console.log(this.payload.description)
109 this.$bus.$emit('image-preview', {
110 url: this.payload.description
111 })
83 } 112 }
84 } 113 }
85 } 114 }
86 </script> 115 </script>
87 116
88 <style lang="stylus" scoped> 117 <style lang="stylus" scoped>
118 .image-element
119 max-width 250px
120 cursor zoom-in
121 width: 100%
122
89 .text 123 .text
90 font-weight bold 124 font-weight bold
125
91 .title 126 .title
92 font-size 16px 127 font-size 16px
93 font-weight 600 128 font-weight 600
94 padding-bottom 10px 129 padding-bottom 10px
130
95 .survey 131 .survey
96 background-color white 132 background-color white
97 color black 133 color black
98 padding 20px 134 padding 20px
99 display flex 135 display flex
100 flex-direction column 136 flex-direction column
137
101 .suggestion 138 .suggestion
102 padding-top 10px 139 padding-top 10px
103 font-size 14px 140 font-size 14px
......
1 <template> 1 <template>
2 <message-bubble :isMine=isMine :message=message> 2 <message-bubble :isMine=isMine :message=message>
3 <!-- el-image在IE下会自动加上用于兼容object-fit的类,该类的样式在没设置图片宽高是会 GG --> 3 <!-- el-image在IE下会自动加上用于兼容object-fit的类,该类的样式在没设置图片宽高是会 GG -->
4 <img class="image-element" :src="imageUrl" @load="onImageLoaded" @click="handlePreview" /> 4 <img class="image-element" :src="imageUrl" @load="onImageLoaded" @click="handlePreview"/>
5 <el-progress 5 <el-progress
6 v-if="showProgressBar" 6 v-if="showProgressBar"
7 :percentage="percentage" 7 :percentage="percentage"
...@@ -12,8 +12,9 @@ ...@@ -12,8 +12,9 @@
12 12
13 <script> 13 <script>
14 import MessageBubble from '../message-bubble' 14 import MessageBubble from '../message-bubble'
15 import { Progress } from 'element-ui' 15 import {Progress} from 'element-ui'
16 import { mapGetters } from 'vuex' 16 import {mapGetters} from 'vuex'
17
17 export default { 18 export default {
18 name: 'ImageElemnt', 19 name: 'ImageElemnt',
19 props: { 20 props: {
......
...@@ -7,12 +7,12 @@ ...@@ -7,12 +7,12 @@
7 > 7 >
8 <div class="col-1" v-if="showAvatar"> 8 <div class="col-1" v-if="showAvatar">
9 <!-- 头像 --> 9 <!-- 头像 -->
10 <avatar :src="avatar" /> 10 <avatar :src="avatar"/>
11 </div> 11 </div>
12 <div class="col-2"> 12 <div class="col-2">
13 <!-- 消息主体 --> 13 <!-- 消息主体 -->
14 <div class="content-wrapper"> 14 <div class="content-wrapper">
15 <message-status-icon v-if="isMine" :message="message" /> 15 <message-status-icon v-if="isMine" :message="message"/>
16 <text-element 16 <text-element
17 v-if="message.type === TIM.TYPES.MSG_TEXT" 17 v-if="message.type === TIM.TYPES.MSG_TEXT"
18 :isMine="isMine" 18 :isMine="isMine"
...@@ -71,9 +71,9 @@ ...@@ -71,9 +71,9 @@
71 :payload="message.payload" 71 :payload="message.payload"
72 :message="message" 72 :message="message"
73 /> 73 />
74 <span v-else>暂未支持的消息类型:{{message.type}}</span> 74 <span v-else>暂未支持的消息类型:{{ message.type }}</span>
75 </div> 75 </div>
76 <message-footer v-if="showMessageHeader" :message="message" /> 76 <message-footer v-if="showMessageHeader" :message="message"/>
77 </div> 77 </div>
78 <div class="col-3"> 78 <div class="col-3">
79 <!-- 消息状态 --> 79 <!-- 消息状态 -->
...@@ -86,14 +86,14 @@ ...@@ -86,14 +86,14 @@
86 :class="messagePosition" 86 :class="messagePosition"
87 > 87 >
88 <!-- 头像 群组没有获取单个头像的接口,暂时无法显示头像--> 88 <!-- 头像 群组没有获取单个头像的接口,暂时无法显示头像-->
89 <div class="col-1" v-if="showAvatar" > 89 <div class="col-1" v-if="showAvatar">
90 <avatar class="group-member-avatar" :src="avatar" @click.native="showGroupMemberProfile"/> 90 <avatar class="group-member-avatar" :src="avatar" @click.native="showGroupMemberProfile"/>
91 </div> 91 </div>
92 <div class="col-2"> 92 <div class="col-2">
93 <!-- 消息主体 --> 93 <!-- 消息主体 -->
94 <message-header v-if="showMessageHeader" :message="message" /> 94 <message-header v-if="showMessageHeader" :message="message"/>
95 <div class="content-wrapper"> 95 <div class="content-wrapper">
96 <message-status-icon v-if="isMine" :message="message" /> 96 <message-status-icon v-if="isMine" :message="message"/>
97 <text-element 97 <text-element
98 v-if="message.type === TIM.TYPES.MSG_TEXT" 98 v-if="message.type === TIM.TYPES.MSG_TEXT"
99 :isMine="isMine" 99 :isMine="isMine"
...@@ -148,7 +148,7 @@ ...@@ -148,7 +148,7 @@
148 :payload="message.payload" 148 :payload="message.payload"
149 :message="message" 149 :message="message"
150 /> 150 />
151 <span v-else>暂未支持的消息类型:{{message.type}}</span> 151 <span v-else>暂未支持的消息类型:{{ message.type }}</span>
152 </div> 152 </div>
153 </div> 153 </div>
154 <div class="col-3"> 154 <div class="col-3">
...@@ -158,18 +158,18 @@ ...@@ -158,18 +158,18 @@
158 158
159 <div class="system-layout" v-if="currentConversationType === TIM.TYPES.CONV_SYSTEM "> 159 <div class="system-layout" v-if="currentConversationType === TIM.TYPES.CONV_SYSTEM ">
160 <div class="col-1"> 160 <div class="col-1">
161 <avatar :src="avatar" :type="currentConversationType" /> 161 <avatar :src="avatar" :type="currentConversationType"/>
162 </div> 162 </div>
163 <div class="col-2"> 163 <div class="col-2">
164 <message-header :message="message" /> 164 <message-header :message="message"/>
165 <group-system-notice-element :payload="message.payload" :message="message" /> 165 <group-system-notice-element :payload="message.payload" :message="message"/>
166 </div> 166 </div>
167 </div> 167 </div>
168 </div> 168 </div>
169 </template> 169 </template>
170 170
171 <script> 171 <script>
172 import { mapState } from 'vuex' 172 import {mapState} from 'vuex'
173 import MessageStatusIcon from './message-status-icon.vue' 173 import MessageStatusIcon from './message-status-icon.vue'
174 import MessageHeader from './message-header' 174 import MessageHeader from './message-header'
175 import MessageFooter from './message-footer' 175 import MessageFooter from './message-footer'
...@@ -284,9 +284,9 @@ export default { ...@@ -284,9 +284,9 @@ export default {
284 groupID: this.message.to, 284 groupID: this.message.to,
285 userIDList: [this.message.from] 285 userIDList: [this.message.from]
286 }) 286 })
287 .then(({ data: { memberList } }) => { 287 .then(({data: {memberList}}) => {
288 if (memberList[0]) { 288 if (memberList[0]) {
289 this.$bus.$emit('showMemberProfile', { event, member: memberList[0] }) 289 this.$bus.$emit('showMemberProfile', {event, member: memberList[0]})
290 } 290 }
291 }) 291 })
292 } 292 }
......
...@@ -12,22 +12,22 @@ ...@@ -12,22 +12,22 @@
12 <i class="iconfont icon-tupian" title="发图片" @click="handleSendImageClick"></i> 12 <i class="iconfont icon-tupian" title="发图片" @click="handleSendImageClick"></i>
13 <i class="el-icon-camera" title="发视频" @click="handleSendVideoClick"></i> 13 <i class="el-icon-camera" title="发视频" @click="handleSendVideoClick"></i>
14 <i class="iconfont icon-wenjian" title="发文件" @click="handleSendFileClick"></i> 14 <i class="iconfont icon-wenjian" title="发文件" @click="handleSendFileClick"></i>
15 <i class="iconfont icon-zidingyi" title="发自定义消息" @click="sendCustomDialogVisible = true"></i> 15 <!-- <i class="iconfont icon-zidingyi" title="发自定义消息" @click="sendCustomDialogVisible = true"></i>-->
16 <el-dropdown> 16 <!-- <el-dropdown>-->
17 <span class="el-dropdown-link"> 17 <!-- <span class="el-dropdown-link">-->
18 <i class="el-icon-phone-outline" v-if="toAccount !== userID" title="语音通话"></i> 18 <!-- <i class="el-icon-phone-outline" v-if="toAccount !== userID" title="语音通话"></i>-->
19 </span> 19 <!-- </span>-->
20 <el-dropdown-menu slot="dropdown"> 20 <!-- <el-dropdown-menu slot="dropdown">-->
21 <el-dropdown-item @click.native="trtcCalling('video')">视频通话</el-dropdown-item> 21 <!-- <el-dropdown-item @click.native="trtcCalling('video')">视频通话</el-dropdown-item>-->
22 <el-dropdown-item @click.native="trtcCalling('audio')">语音通话</el-dropdown-item> 22 <!-- <el-dropdown-item @click.native="trtcCalling('audio')">语音通话</el-dropdown-item>-->
23 </el-dropdown-menu> 23 <!-- </el-dropdown-menu>-->
24 </el-dropdown> 24 <!-- </el-dropdown>-->
25 <div class="group-live-icon-box" 25 <!-- <div class="group-live-icon-box"-->
26 v-if="currentConversationType === TIM.TYPES.CONV_GROUP && groupProfile.type !== 'AVChatRoom'" title="群直播" 26 <!-- v-if="currentConversationType === TIM.TYPES.CONV_GROUP && groupProfile.type !== 'AVChatRoom'" title="群直播"-->
27 @click="groupLive"> 27 <!-- @click="groupLive">-->
28 <i class="group-live-icon"></i> 28 <!-- <i class="group-live-icon"></i>-->
29 <i class="group-live-icon-hover"></i> 29 <!-- <i class="group-live-icon-hover"></i>-->
30 </div> 30 <!-- </div>-->
31 </div> 31 </div>
32 <el-dialog title="发自定义消息" :visible.sync="sendCustomDialogVisible" width="30%"> 32 <el-dialog title="发自定义消息" :visible.sync="sendCustomDialogVisible" width="30%">
33 <el-form label-width="100px"> 33 <el-form label-width="100px">
......
1 <template> 1 <template>
2 <div class="container"> 2 <div class="container">
3 <div 3 <div class="loading" v-loading="showLoading" element-loading-text="正在拼命初始化..."
4 class="loading" 4 element-loading-background="rgba(0, 0, 0, 0.8)">
5 v-loading="showLoading"
6 element-loading-text="正在拼命初始化..."
7 element-loading-background="rgba(0, 0, 0, 0.8)"
8 >
9 <div class="chat-wrapper"> 5 <div class="chat-wrapper">
10 <el-row> 6 <el-row>
11 <el-col :xs="10" :sm="10" :md="8" :lg="8" :xl="7"> 7 <el-col :xs="10" :sm="10" :md="8" :lg="8" :xl="7">
...@@ -76,10 +72,13 @@ export default { ...@@ -76,10 +72,13 @@ export default {
76 this.$store.commit('toggleIsLogin', true) 72 this.$store.commit('toggleIsLogin', true)
77 this.$store.commit('startComputeCurrent') 73 this.$store.commit('startComputeCurrent')
78 this.$store.commit({ 74 this.$store.commit({
79 type: 'GET_USER_INFO', userID: user.id, 75 type: 'GET_USER_INFO',
76 userID: user.id,
80 userSig: user.sign, 77 userSig: user.sign,
81 sdkAppID: window.genTestUserSig('').SDKAppID 78 sdkAppID: window.genTestUserSig('').SDKAppID
82 }) 79 })
80 Helper.contactList().then(res => this.$store.commit('updateFriendList', res.data))
81 // Helper.groupList({size: 20}).then(res => this.$store.commit('updateGroupList', res.data))
83 // this.$store.commit('showMessage', {type: 'success', message: '登录成功'}) 82 // this.$store.commit('showMessage', {type: 'success', message: '登录成功'})
84 }) 83 })
85 .catch(error => { 84 .catch(error => {
...@@ -110,7 +109,7 @@ export default { ...@@ -110,7 +109,7 @@ export default {
110 // 会话列表更新 109 // 会话列表更新
111 this.tim.on(this.TIM.EVENT.CONVERSATION_LIST_UPDATED, this.onUpdateConversationList) 110 this.tim.on(this.TIM.EVENT.CONVERSATION_LIST_UPDATED, this.onUpdateConversationList)
112 // 群组列表更新 111 // 群组列表更新
113 this.tim.on(this.TIM.EVENT.GROUP_LIST_UPDATED, this.onUpdateGroupList) 112 // this.tim.on(this.TIM.EVENT.GROUP_LIST_UPDATED, this.onUpdateGroupList)
114 // 网络监测 113 // 网络监测
115 this.tim.on(this.TIM.EVENT.NET_STATE_CHANGE, this.onNetStateChange) 114 this.tim.on(this.TIM.EVENT.NET_STATE_CHANGE, this.onNetStateChange)
116 // 已读回执 115 // 已读回执
...@@ -188,9 +187,9 @@ export default { ...@@ -188,9 +187,9 @@ export default {
188 onUpdateConversationList(event) { 187 onUpdateConversationList(event) {
189 this.$store.commit('updateConversationList', event.data) 188 this.$store.commit('updateConversationList', event.data)
190 }, 189 },
191 onUpdateGroupList(event) { 190 // onUpdateGroupList(event) {
192 this.$store.commit('updateGroupList', event.data) 191 // this.$store.commit('updateGroupList', event.data)
193 }, 192 // },
194 onReceiveGroupSystemNotice(event) { 193 onReceiveGroupSystemNotice(event) {
195 const isKickedout = event.data.type === 4 194 const isKickedout = event.data.type === 4
196 const isCurrentConversation = 195 const isCurrentConversation =
......
1 import Vue from 'vue' 1 import Vue from 'vue'
2 import {Button, Checkbox, CheckboxGroup, Col, Collapse, CollapseItem, Dialog, Dropdown, DropdownItem, DropdownMenu, Input, Loading, MessageBox, Row} from 'element-ui' 2 import {Button, Checkbox, CheckboxGroup, Col, Collapse, CollapseItem, Dialog, Dropdown, DropdownItem, DropdownMenu, Image, InfiniteScroll, Input, Loading, MessageBox, Row} from 'element-ui'
3 import Avatar from './components/avatar.vue' 3 import Avatar from './components/avatar.vue'
4 import Index from './index.vue' 4 import Index from './index.vue'
5 import store from './store/index' 5 import store from './store/index'
...@@ -39,6 +39,8 @@ Vue.use(Checkbox) ...@@ -39,6 +39,8 @@ Vue.use(Checkbox)
39 Vue.use(CheckboxGroup) 39 Vue.use(CheckboxGroup)
40 Vue.use(Collapse) 40 Vue.use(Collapse)
41 Vue.use(CollapseItem) 41 Vue.use(CollapseItem)
42 Vue.use(InfiniteScroll)
43 Vue.use(Image)
42 Vue.component('avatar', Avatar) 44 Vue.component('avatar', Avatar)
43 new Vue({ 45 new Vue({
44 render: h => h(Index) 46 render: h => h(Index)
......
...@@ -15,7 +15,8 @@ export default new Vuex.Store({ ...@@ -15,7 +15,8 @@ export default new Vuex.Store({
15 state: { 15 state: {
16 current: Date.now(), // 当前时间 16 current: Date.now(), // 当前时间
17 intervalID: 0, 17 intervalID: 0,
18 message: undefined 18 message: undefined,
19 activeMenu: '',
19 }, 20 },
20 getters: { 21 getters: {
21 hidden(state) { 22 hidden(state) {
...@@ -28,6 +29,7 @@ export default new Vuex.Store({ ...@@ -28,6 +29,7 @@ export default new Vuex.Store({
28 } 29 }
29 }, 30 },
30 mutations: { 31 mutations: {
32 setActiveMenu: (state, active) => state.activeMenu = active,
31 startComputeCurrent(state) { 33 startComputeCurrent(state) {
32 state.intervalID = setInterval(() => { 34 state.intervalID = setInterval(() => {
33 state.current = Date.now() 35 state.current = Date.now()
......
1 const friendModules = { 1 const friendModules = {
2 state: { 2 state: {
3 friendList: [], 3 friendList: [],
4 createGroupModelVisible: false 4 adminList: [],
5 schemeList: [],
6 userList: [],
7 createGroupModelVisible: false,
5 }, 8 },
9 getters: {},
6 mutations: { 10 mutations: {
7 upadteFriendList(state, friendList) { 11 updateFriendList(state, friendList) {
8 state.friendList = friendList 12 // state.friendList = friendList
13 state.userList = friendList.user
14 state.adminList = friendList.admin
15 state.schemeList = friendList.scheme
9 }, 16 },
10 reset(state) { 17 reset(state) {
11 Object.assign(state, { 18 Object.assign(state, {friendList: [], createGroupModelVisible: false})
12 friendList: [],
13 createGroupModelVisible: false
14 })
15 } 19 }
16 } 20 }
17 } 21 }
......
...@@ -24,4 +24,16 @@ export default class Helper { ...@@ -24,4 +24,16 @@ export default class Helper {
24 return Promise.resolve({id: esm_id, sign: window.genTestUserSig(esm_id).userSig}) 24 return Promise.resolve({id: esm_id, sign: window.genTestUserSig(esm_id).userSig})
25 }) 25 })
26 } 26 }
27
28 static contactList() {
29 return request.get('im/contacts')
30 }
31
32 static groupList(params = {}) {
33 return request.get('im/groups', {params})
34 }
35
36 static joinGroup(id) {
37 return request.put(`im/groups/${id}`)
38 }
27 } 39 }
......
1 @charset "utf-8";
2 html {
3 font-family: PingFangSC-Light, HelveticaNeue-Light, "Helvetica Neue Light", "Helvetica Neue", Helvetica, STHeiTi, sans-serif;
4 font-size: 14px
5 }
6
7 body, dd, dl, h1, h2, h3, ol, p, ul {
8 margin: 0
9 }
10
11 ol, ul {
12 padding: 0
13 }
14
15 body {
16 -webkit-user-select: none;
17 -webkit-tap-highlight-color: transparent;
18 outline: 0
19 }
20
21 h1, h2, h3 {
22 font-size: 100%;
23 font-weight: 400
24 }
25
26 table {
27 border-collapse: collapse;
28 border-spacing: 0
29 }
30
31 img {
32 border: 0
33 }
34
35 li {
36 list-style-type: none
37 }
38
39 button, input, option, select, textarea {
40 font: inherit;
41 outline: 0;
42 -webkit-appearance: none;
43 border: 0
44 }
45
46 button {
47 padding: 0;
48 margin: 0;
49 border: 0
50 }
51
52 a {
53 -webkit-touch-callout: none;
54 text-decoration: none
55 }
56
57 em, i {
58 font-style: normal
59 }
60
61 .video-page {
62 position: fixed;
63 top: 0;
64 width: 100%
65 }
66
67 .video-play video {
68 width: 100%;
69 height: 100%;
70 background-color: #fff
71 }
72
73 .video-pane {
74 position: absolute;
75 top: 0;
76 left: 0;
77 bottom: 0;
78 right: 0;
79 z-index: 1000
80 }
81
82 .video-pane .video-pane-head {
83 height: 20%;
84 position: relative;
85 width: 100%
86 }
87
88 .video-pane .video-pane-body {
89 height: 80%;
90 position: fixed;
91 z-index: 1000;
92 width: 100%;
93 bottom: 0
94 }
95
96 .video-close {
97 position: absolute;
98 top: 0;
99 right: 0;
100 background: url(../img/drop_out.png) no-repeat;
101 background-size: 14px 14px;
102 width: 14px;
103 height: 14px;
104 margin: 15px
105 }
106
107 .video-close:focus, .video-close:hover {
108 background-image: url(../img/drop_out_hover.png)
109 }
110
111 .user-info-num {
112 font-size: 13px;
113 color: #fff
114 }
115
116 .video-pane-info {
117 display: inline-block;
118 background: url(../img/back.png);
119 border-radius: 51px;
120 height: 51px;
121 margin: 15px
122 }
123
124 .video-info {
125 z-index: 2;
126 position: relative;
127 padding: 3px
128 }
129
130 .user-img {
131 display: inline-block
132 }
133
134 .user-info-text {
135 display: inline-block;
136 padding-left: 10px;
137 padding-right: 20px;
138 vertical-align: top;
139 padding-top: 5px;
140 color: #fff;
141 max-width: 200px
142 }
143
144 .user-info-name {
145 line-height: 16px
146 }
147
148 .user-icon-fans {
149 background: url(../img/visitor_white.png) no-repeat
150 }
151
152 .user-icon-like {
153 background: url(../img/like_white.png) no-repeat;
154 margin-left: 10px
155 }
156
157 .user-icon-fans, .user-icon-like {
158 background-size: 11px 10px;
159 width: 11px;
160 height: 10px;
161 display: inline-block;
162 margin-right: 2px
163 }
164
165 .video-discuss {
166 position: absolute;
167 bottom: 0;
168 left: 0;
169 right: 0
170 }
171
172 .video-sms-list {
173 color: #fff;
174 margin: 0 15px
175 }
176
177 .video-sms-list li {
178 margin-bottom: 5px
179 }
180
181 .video-sms-list li:nth-child(1) {
182 opacity: .4
183 }
184
185 .video-sms-list li:nth-child(2) {
186 opacity: .6
187 }
188
189 .video-sms-list li:nth-child(3) {
190 opacity: .8
191 }
192
193 .video-sms-pane {
194 display: inline-block
195 }
196
197 .video-sms-text {
198 padding: 2px 10px;
199 font-size: 14px;
200 background-color: #fff;
201 border-radius: 10px;
202 text-align: left;
203 max-width: 250px;
204 line-height: 18px;
205 color: #000;
206 word-wrap: break-word
207 }
208
209 .video-sms-text span {
210 padding-right: 10px;
211 vertical-align: top;
212 color: #000
213 }
214
215 .video-sms-text span.user-name-green {
216 color: #1fbcb6
217 }
218
219 .video-sms-text span.user-name-red {
220 color: #f12b5b
221 }
222
223 .video-sms-text span.user-name-blue {
224 color: #2b84f1
225 }
226
227 .video-sms-text span.user-name-org {
228 color: #ff7906
229 }
230
231 .video-discuss-tool {
232 margin: 25px 15px 15px
233 }
234
235 .video-discuss-sms {
236 background: url(../img/comment.png) no-repeat;
237 background-size: 35px 35px;
238 display: inline-block;
239 width: 35px;
240 height: 35px
241 }
242
243 .video-discuss-sms:focus, .video-discuss-sms:hover {
244 background-image: url(../img/comment_hover.png)
245 }
246
247 .video-discuss-like {
248 background: url(../img/like.png) no-repeat;
249 background-size: 35px 35px;
250 display: inline-block;
251 width: 35px;
252 height: 35px;
253 position: absolute;
254 right: 15px
255 }
256
257 .video-discuss-like:focus, .video-discuss-like:hover {
258 background-image: url(../img/like_hover.png)
259 }
260
261 .video-discuss-form {
262 height: 30px;
263 background: url(../img/form-back.png);
264 padding: 8px 60px 10px 8px;
265 position: relative
266 }
267
268 .video-discuss-input {
269 width: 85%;
270 height: 30px;
271 vertical-align: top;
272 padding: 0 13% 0 2%;
273 border-radius: 2px
274 }
275
276 .video-discuss-button {
277 background-color: #dc4b53;
278 height: 30px;
279 color: #fff;
280 width: 45px;
281 position: absolute;
282 right: 10px;
283 font-size: 14px;
284 top: 8px;
285 border-radius: 2px
286 }
287
288 .video-discuss-face {
289 background: url(../img/face.png) no-repeat;
290 background-size: 20px 20px;
291 width: 20px;
292 height: 20px;
293 display: inline-block;
294 right: 65px;
295 top: 12px;
296 position: absolute
297 }
298
299 .video-discuss-face:focus, .video-discuss-face:hover {
300 background-image: url(../img/face_hover.png)
301 }
302
303 .like-icon {
304 background: url(../img/like_icon_1.png) no-repeat;
305 background-size: 19px 17px;
306 width: 19px;
307 height: 17px;
308 position: absolute;
309 right: 24px;
310 margin-top: -15px;
311 opacity: 0;
312 -webkit-animation-duration: 1.5s;
313 animation-duration: 1.5s;
314 -webkit-animation-fill-mode: both;
315 animation-fill-mode: both
316 }
317
318 .like-icon.green {
319 background-image: url(../img/like_icon_2.png)
320 }
321
322 .like-icon.blue {
323 background-image: url(../img/like_icon_3.png)
324 }
325
326 .like-icon.red {
327 background-image: url(../img/like_icon_4.png)
328 }
329
330 @-webkit-keyframes zoomIn {
331 from {
332 opacity: 0;
333 -webkit-transform: scale3d(.3, .3, .3);
334 transform: scale3d(.3, .3, .3);
335 margin-top: 0
336 }
337 50% {
338 opacity: 1
339 }
340 100% {
341 opacity: 0;
342 margin-top: -60px;
343 -webkit-transform: scale3d(1, 1, 1);
344 transform: scale3d(1, 1, 1)
345 }
346 }
347
348 @keyframes zoomIn {
349 from {
350 opacity: 0;
351 -webkit-transform: scale3d(.3, .3, .3);
352 transform: scale3d(.3, .3, .3);
353 margin-top: 0
354 }
355 50% {
356 opacity: 1
357 }
358 100% {
359 opacity: 0;
360 margin-top: -60px;
361 -webkit-transform: scale3d(1, 1, 1);
362 transform: scale3d(1, 1, 1)
363 }
364 }
365
366 .zoomIn {
367 -webkit-animation-name: zoomIn;
368 animation-name: zoomIn
369 }
370
371 .video-discuss-emotion {
372 height: 140px;
373 background-color: #fff;
374 padding: 8px;
375 position: relative
376 }
377
378 .video-emotion-pane {
379 width: 100%;
380 height: 100%
381 }
382
383 .video-emotion-pane ul {
384 margin: 12px;
385 padding: 0;
386 overflow: hidden;
387 border-top: 1px #CCC solid;
388 border-left: 1px #CCC solid;
389 list-style: none;
390 width: 333px
391 }
392
393 .video-emotion-pane ul li {
394 float: left;
395 border-right: 1px #CCC solid;
396 border-bottom: 1px #CCC solid;
397 height: 30px;
398 line-height: 30px;
399 width: 32px;
400 margin: 0;
401 padding: 4px 2px;
402 text-align: center
403 }
404
405 .video-emotion-pane ul li img {
406 width: 24px;
407 height: 24px;
408 vertical-align: middle
409 }
410
411 #MAXIM {
412 content: "tig201605241501026"
413 }
414
415 #login_dialog{
416 display: none;
417 height: 100%;
418 width: 100%;
419 background: rgba(0, 0, 0, 0.5);
420 position: absolute;
421 }
422
423 .login_dialog_p{display: inline-block;color: #fff;text-align: right;width: 54px;}
424
425 #login_dialog_all{margin-top: 200px;margin-left: 50px;}
426
427 .install_div{margin:10px;}
428 .install_div input{padding: 5px;width: 60%;}
429 .install_button_div{width:100%;text-align: center;}
430 .install_button_div button{color: #fff;border-radius: 4px;background: red;padding: 4px 20px;}
...\ No newline at end of file ...\ No newline at end of file
1 /*eslint-disable*/
2 /*
3 * Module: GenerateTestUserSig
4 *
5 * Function: 用于生成测试用的 UserSig,UserSig 是腾讯云为其云服务设计的一种安全保护签名。
6 * 其计算方法是对 SDKAppID、UserID 和 EXPIRETIME 进行加密,加密算法为 HMAC-SHA256。
7 *
8 * Attention: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
9 *
10 * 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
11 * 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
12 * 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
13 *
14 * 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
15 * 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
16 *
17 * Reference:https://cloud.tencent.com/document/product/647/17275#Server
18 */
19 function genTestUserSig(userID) {
20 /**
21 * 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。
22 *
23 * 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ) 创建应用,即可看到 SDKAppId,
24 * 它是腾讯云用于区分客户的唯一标识。
25 */
26 var SDKAPPID = 0;
27
28 /**
29 * 签名过期时间,建议不要设置的过短
30 * <p>
31 * 时间单位:秒
32 * 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天
33 */
34 var EXPIRETIME = 604800;
35
36 /**
37 * 计算签名用的加密密钥,获取步骤如下:
38 *
39 * step1. 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ),如果还没有应用就创建一个,
40 * step2. 单击“应用配置”进入基础配置页面,并进一步找到“帐号体系集成”部分。
41 * step3. 点击“查看密钥”按钮,就可以看到计算 UserSig 使用的加密的密钥了,请将其拷贝并复制到如下的变量中
42 *
43 * 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
44 * 文档:https://cloud.tencent.com/document/product/647/17275#Server
45 */
46 var SECRETKEY = '';
47
48 var generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME);
49 var userSig = generator.genTestUserSig(userID);
50 return {
51 sdkAppID: SDKAPPID,
52 userSig: userSig
53 };
54 }
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
1 //监听 申请加群 系统消息
2
3 function onApplyJoinGroupRequestNotify(notify) {
4 webim.Log.warn("执行 加群申请 回调:" + JSON.stringify(notify));
5 var timestamp = notify.MsgTime;
6 var reportTypeCh = "[申请加群]";
7 var content = notify.Operator_Account + "申请加入你的群";
8 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, timestamp);
9 }
10
11 //监听 申请加群被同意 系统消息
12
13 function onApplyJoinGroupAcceptNotify(notify) {
14 webim.Log.warn("执行 申请加群被同意 回调:" + JSON.stringify(notify));
15 var reportTypeCh = "[申请加群被同意]";
16 var content = notify.Operator_Account + "同意你的加群申请,附言:" + notify.RemarkInfo;
17 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
18 }
19 //监听 申请加群被拒绝 系统消息
20
21 function onApplyJoinGroupRefuseNotify(notify) {
22 webim.Log.warn("执行 申请加群被拒绝 回调:" + JSON.stringify(notify));
23 var reportTypeCh = "[申请加群被拒绝]";
24 var content = notify.Operator_Account + "拒绝了你的加群申请,附言:" + notify.RemarkInfo;
25 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
26 }
27 //监听 被踢出群 系统消息
28
29 function onKickedGroupNotify(notify) {
30 webim.Log.warn("执行 被踢出群 回调:" + JSON.stringify(notify));
31 var reportTypeCh = "[被踢出群]";
32 var content = "你被管理员" + notify.Operator_Account + "踢出该群";
33 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
34 }
35 //监听 解散群 系统消息
36
37 function onDestoryGroupNotify(notify) {
38 webim.Log.warn("执行 解散群 回调:" + JSON.stringify(notify));
39 var reportTypeCh = "[群被解散]";
40 var content = "群主" + notify.Operator_Account + "已解散该群";
41 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
42 }
43 //监听 创建群 系统消息
44
45 function onCreateGroupNotify(notify) {
46 webim.Log.warn("执行 创建群 回调:" + JSON.stringify(notify));
47 var reportTypeCh = "[创建群]";
48 var content = "你创建了该群";
49 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
50 }
51 //监听 被邀请加群 系统消息
52
53 function onInvitedJoinGroupNotify(notify) {
54 webim.Log.warn("执行 被邀请加群 回调: " + JSON.stringify(notify));
55 var reportTypeCh = "[被邀请加群]";
56 var content = "你被管理员" + notify.Operator_Account + "邀请加入该群";
57 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
58 }
59 //监听 主动退群 系统消息
60
61 function onQuitGroupNotify(notify) {
62 webim.Log.warn("执行 主动退群 回调: " + JSON.stringify(notify));
63 var reportTypeCh = "[主动退群]";
64 var content = "你退出了该群";
65 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
66 }
67 //监听 被设置为管理员 系统消息
68
69 function onSetedGroupAdminNotify(notify) {
70 webim.Log.warn("执行 被设置为管理员 回调:" + JSON.stringify(notify));
71 var reportTypeCh = "[被设置为管理员]";
72 var content = "你被群主" + notify.Operator_Account + "设置为管理员";
73 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
74 }
75 //监听 被取消管理员 系统消息
76
77 function onCanceledGroupAdminNotify(notify) {
78 webim.Log.warn("执行 被取消管理员 回调:" + JSON.stringify(notify));
79 var reportTypeCh = "[被取消管理员]";
80 var content = "你被群主" + notify.Operator_Account + "取消了管理员资格";
81 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
82 }
83 //监听 群被回收 系统消息
84
85 function onRevokeGroupNotify(notify) {
86 webim.Log.warn("执行 群被回收 回调:" + JSON.stringify(notify));
87 var reportTypeCh = "[群被回收]";
88 var content = "该群已被回收";
89 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
90 }
91 //监听 用户自定义 群系统消息
92
93 function onCustomGroupNotify(notify) {
94 webim.Log.warn("执行 用户自定义系统消息 回调:" + JSON.stringify(notify));
95 var reportTypeCh = "[用户自定义系统消息]";
96 var content = notify.UserDefinedField; //群自定义消息数据
97 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
98 }
99
100 //监听 群资料变化 群提示消息
101
102 function onGroupInfoChangeNotify(groupInfo) {
103 webim.Log.warn("执行 群资料变化 回调: " + JSON.stringify(groupInfo));
104 var groupId = groupInfo.GroupId;
105 var newFaceUrl = groupInfo.GroupFaceUrl; //新群组图标, 为空,则表示没有变化
106 var newName = groupInfo.GroupName; //新群名称, 为空,则表示没有变化
107 var newOwner = groupInfo.OwnerAccount; //新的群主id, 为空,则表示没有变化
108 var newNotification = groupInfo.GroupNotification; //新的群公告, 为空,则表示没有变化
109 var newIntroduction = groupInfo.GroupIntroduction; //新的群简介, 为空,则表示没有变化
110
111 if (newName) {
112 //更新群组列表的群名称
113 //To do
114 webim.Log.warn("群id=" + groupId + "的新名称为:" + newName);
115 }
116 }
117
118 //显示一条群组系统消息
119
120 function showGroupSystemMsg(type, typeCh, group_id, group_name, msg_content, msg_time) {
121 var sysMsgStr = "收到一条群系统消息: type=" + type + ", typeCh=" + typeCh + ",群ID=" + group_id + ", 群名称=" + group_name + ", 内容=" + msg_content + ", 时间=" + webim.Tool.formatTimeStamp(msg_time);
122 webim.Log.warn(sysMsgStr);
123 alert(sysMsgStr);
124 }
...\ No newline at end of file ...\ No newline at end of file
This diff could not be displayed because it is too large.
1 本文主要介绍如何快速地运行云通信 WebIM Demo 工程,您只需参考如下步骤依次执行即可。
2
3 ## 1. 创建新的应用
4 进入登录云通信 IM [控制台](https://console.cloud.tencent.com/avc) 创建一个新的应用,获得 SDKAppID,SDKAppID 是腾讯云后台用来区分不同云通信应用的唯一标识,在第4步中会用到。
5 ![](https://main.qcloudimg.com/raw/b9d211494b6ec8fcea765d1518b228a1.png)
6
7 接下来,点击应用进入**快速上手**页面,参考页面上指引的“第一步”、“第二步”和“第三步”操作,即可快速跑通 Demo。
8
9 ## 2. 下载 SDK+Demo 源码
10 “快速上手”页面中第一步里的几个链接地址分别为各个平台的 SDK 和 Demo 源码,点击会跳转到 Github 上,如果您当前网络访问 Github 太慢,可以在项目首页中找到镜像下载地址。
11 ![](https://main.qcloudimg.com/raw/d56b4e4434da42d1a3b8e3540cf6718e.png)
12
13 ## 3. 查看并拷贝加密密钥
14 点击**查看密钥**按钮,即可看到用于计算 UserSig 的加密密钥,点击“复制密钥”按钮,可以将密钥拷贝到剪贴板中。
15 ![](https://main.qcloudimg.com/raw/5843542ec2e0446d326d7d44f96a5ec0.png)
16
17 <h2 id="CopyKey"> 4. 粘贴密钥到Demo工程的指定文件中 </h2>
18 我们在各个平台的 Demo 的源码工程中都提供了一个叫做 “GenerateTestUserSig” 的文件,它可以通过 HMAC-SHA256 算法本地计算出 UserSig,用于快速跑通 Demo。您只需要将第1步中获得的 SDKAppID 和第3步中获得的加密密钥拷贝到文件中的指定位置即可,如下所示:
19
20 ![](https://main.qcloudimg.com/raw/9275a5f99bf00467eac6c34f6ddd3ca5.jpg)
21
22 ## 5. 编译运行
23 使用 Chrome 浏览器打开 Demo 根目录下的 **index.html** 即可运行 Demo。
24 - 登录成功后,可以进行查找好友,建群,聊天等操作:
25 ![](https://main.qcloudimg.com/raw/87e6f5eae834907cab89f50d5ce49b49.png)
26
27 - 搜索并添加好友。
28 ![](https://main.qcloudimg.com/raw/ef4c39f1ec649ad4f10cd8764ca51d1c.png)
29
30 - 选择好友发消息。
31 ![](https://main.qcloudimg.com/raw/ff8c787aa814edefd96468de2da59f26.png)
32
33 - 给好友发消息。
34 ![](https://main.qcloudimg.com/raw/d55732975bb5d3e8e44a283e1a26ba4b.png)
...\ No newline at end of file ...\ No newline at end of file
1 .bootstrap-table .table {
2 margin-bottom: 0 !important;
3 border-bottom: 1px solid #dddddd;
4 border-collapse: collapse !important;
5 border-radius: 1px;
6 }
7
8 .fixed-table-container {
9 position: relative;
10 clear: both;
11 border: 1px solid #dddddd;
12 border-radius: 4px;
13 -webkit-border-radius: 4px;
14 -moz-border-radius: 4px;
15 }
16
17 .fixed-table-header {
18 overflow: hidden;
19 border-radius: 4px 4px 0 0;
20 -webkit-border-radius: 4px 4px 0 0;
21 -moz-border-radius: 4px 4px 0 0;
22 }
23
24 .fixed-table-body {
25 overflow-x: auto;
26 overflow-y: auto;
27 height: 100%;
28 }
29
30 .fixed-table-container table {
31 width: 100%;
32 }
33
34 .fixed-table-container thead th {
35 height: 0;
36 padding: 0;
37 margin: 0;
38 border-left: 1px solid #dddddd;
39 }
40
41 .fixed-table-container thead th:first-child {
42 border-left: none;
43 border-top-left-radius: 4px;
44 -webkit-border-top-left-radius: 4px;
45 -moz-border-radius-topleft: 4px;
46 }
47
48 .fixed-table-container thead th .th-inner {
49 padding: 8px;
50 line-height: 24px;
51 vertical-align: top;
52 overflow: hidden;
53 text-overflow: ellipsis;
54 white-space: nowrap;
55 }
56
57 .fixed-table-container thead th .sortable {
58 cursor: pointer;
59 }
60
61 .fixed-table-container tbody td {
62 border-left: 1px solid #dddddd;
63 }
64
65 .fixed-table-container tbody tr:first-child td {
66 border-top: none;
67 }
68
69 .fixed-table-container tbody td:first-child {
70 border-left: none;
71 }
72
73 /* the same color with .active */
74 .fixed-table-container tbody .selected td {
75 background-color: #f5f5f5;
76 }
77
78 .fixed-table-container .bs-checkbox {
79 text-align: center;
80 }
81
82 .fixed-table-container .bs-checkbox .th-inner {
83 padding: 8px 0;
84 }
85
86 .fixed-table-container input[type="radio"],
87 .fixed-table-container input[type="checkbox"] {
88 margin: 0 auto !important;
89 }
90
91 .fixed-table-container .no-records-found {
92 text-align: center;
93 }
94
95
96 .fixed-table-pagination .pagination,
97 .fixed-table-pagination .pagination-detail {
98 margin-top: 10px;
99 margin-bottom: 10px;
100 }
101
102 .fixed-table-pagination .pagination a {
103 padding: 6px 12px;
104 line-height: 1.428571429;
105 }
106
107 .fixed-table-pagination .pagination-info {
108 line-height: 34px;
109 margin-right: 5px;
110 }
111
112 .fixed-table-pagination .btn-group {
113 position: relative;
114 display: inline-block;
115 vertical-align: middle;
116 }
117
118 .fixed-table-pagination .dropup .dropdown-menu {
119 margin-bottom: 0;
120 }
121
122 .fixed-table-pagination .page-list {
123 display: inline-block;
124 }
125
126 .fixed-table-toolbar .columns-left {
127 margin-right: 5px;
128 }
129
130 .fixed-table-toolbar .columns-right {
131 margin-left: 5px;
132 }
133
134 .fixed-table-toolbar .columns label {
135 display: block;
136 padding: 3px 20px;
137 clear: both;
138 font-weight: normal;
139 line-height: 1.428571429;
140 }
141
142 .fixed-table-toolbar .bars,
143 .fixed-table-toolbar .search,
144 .fixed-table-toolbar .columns {
145 position: relative;
146 margin-top: 10px;
147 margin-bottom: 10px;
148 line-height: 34px;
149 }
150
151 .fixed-table-pagination li.disabled a {
152 pointer-events: none;
153 cursor: default;
154 }
155
156 .fixed-table-loading {
157 display: none;
158 position: absolute;
159 top: 42px;
160 right: 0;
161 bottom: 0;
162 left: 0;
163 z-index: 99;
164 background-color: #fff;
165 text-align: center;
166 }
167
168 .fixed-table-body .card-view .title {
169 font-weight: bold;
170 display: inline-block;
171 min-width: 30%;
172 text-align: left !important;
173 }
174
175 /* support bootstrap 2 */
176 .fixed-table-body thead th .th-inner {
177 box-sizing: border-box;
178 }
179
180 .table th, .table td {
181 vertical-align: middle;
182 box-sizing: border-box;
183 }
184
185 .fixed-table-toolbar .dropdown-menu {
186 text-align: left;
187 max-height: 300px;
188 overflow: auto;
189 }
190
191 .fixed-table-toolbar .btn-group>.btn-group {
192 display: inline-block;
193 margin-left: -1px !important;
194 }
195
196 .fixed-table-toolbar .btn-group>.btn-group>.btn {
197 border-radius: 0;
198 }
199
200 .fixed-table-toolbar .btn-group>.btn-group:first-child>.btn {
201 border-top-left-radius: 4px;
202 border-bottom-left-radius: 4px;
203 }
204
205 .fixed-table-toolbar .btn-group>.btn-group:last-child>.btn {
206 border-top-right-radius: 4px;
207 border-bottom-right-radius: 4px;
208 }
209
210 .bootstrap-table .table>thead>tr>th {
211 vertical-align: bottom;
212 border-bottom: 2px solid #ddd;
213 }
214
215 /* support bootstrap 3 */
216 .bootstrap-table .table thead>tr>th {
217 padding: 0;
218 margin: 0;
219 }
220
221 .pull-right .dropdown-menu {
222 right: 0;
223 left: auto;
224 }
225
226 /* calculate scrollbar width */
227 p.fixed-table-scroll-inner {
228 width: 100%;
229 height: 200px;
230 }
231
232 div.fixed-table-scroll-outer {
233 top: 0;
234 left: 0;
235 visibility: hidden;
236 width: 200px;
237 height: 150px;
238 overflow: hidden;
239 }
...\ No newline at end of file ...\ No newline at end of file
This diff could not be displayed because it is too large.
1 /*
2 To change this license header, choose License Headers in Project Properties.
3 To change this template file, choose Tools | Templates
4 and open the template in the editor.
5 */
6 /*
7 Created on : 2015-7-6, 15:55:30
8 Author : peakerdong
9 */
10 body {
11 background: #2f2f2f;
12 }
13
14 #login {
15 display: block;
16 margin: 150px auto;
17 text-align: center;
18 }
19
20 .aio {
21 display: none;
22 width: 734px;
23 border: 1px black solid;
24 padding: 0px;
25 background: white;
26 margin: 20px auto;
27 font: 10px/1.5 "微软雅黑";
28 }
29
30 .titlebar {
31 height: 82px;
32 background: #5c95b3;
33 }
34
35 .titlebar #p_my_face {
36 position: relative;
37 width: 60px;
38 height: 60px;
39 border: 1px white solid;
40 margin: 10px;
41 float: left;
42 }
43
44 .titlebar #t_my_name {
45 position: relative;
46 top: 10px;
47 left: 10px;
48 float: left;
49 font-size: 20px;
50 color: white;
51 }
52
53 .titlebar #t_my_menu {
54 width: 150px;
55 position: relative;
56 top: 5px;
57 right: 5px;
58 float: right;
59
60 }
61
62 .sesspart {
63 clear: both;
64 float: left;
65 width: 208px;
66 height: 535px;
67 background: #d7eaf3;
68 }
69
70 .accordion {
71 margin-bottom: 18px;
72 }
73
74 .accordion-group {
75 margin-bottom: 2px;
76 border: 1px solid #e5e5e5;
77 -webkit-border-radius: 4px;
78 -moz-border-radius: 4px;
79 border-radius: 4px;
80 }
81
82 .accordion-heading {
83 border-bottom: 0;
84 background-color: bisque;
85 }
86
87 .accordion-heading .accordion-toggle {
88 display: block;
89 padding: 8px 15px;
90 font-size: medium;
91 }
92
93 .accordion-inner {
94 padding: 9px 15px;
95 border-top: 1px solid #e5e5e5;
96 }
97 .sesslist-recent {
98 height: 450px;
99 background: #f5f5f5;
100 border-width: 0px 1px 0px 0px;
101 border-color: #d5d6d7;
102 border-style: solid;
103 //overflow: auto;
104 }
105
106
107 .sesslist {
108 /* height: 400px; */
109 height: 450px;
110 background: #f5f5f5;
111 border-width: 0px 1px 0px 0px;
112 border-color: #d5d6d7;
113 border-style: solid;
114 overflow: auto;
115 }
116
117 .sesslist-group {
118 /* height: 400px; */
119 height: 450px;
120 background: #f5f5f5;
121 border-width: 0px 1px 0px 0px;
122 border-color: #d5d6d7;
123 border-style: solid;
124 overflow: auto;
125 }
126
127 .sessinfo {
128 clear: both;
129 height: 50px;
130 border-width: 0px 0px 1px 0px;
131 border-color: #d5d6d7;
132 border-style: solid;
133 }
134
135 .sessinfo-sel {
136 clear: both;
137 height: 50px;
138 border-width: 0px 0px 1px 0px;
139 border-color: #d5d6d7;
140 border-style: solid;
141 background: #d7eaf3;
142 }
143
144 .face {
145 float: left;
146 width: 40px;
147 height: 40px;
148 margin: 5px 5px 5px 10px;
149 }
150
151 .name {
152 float: left;
153 height: 20px;
154 text-indent: 2px;
155 font-size: 12px;
156 color: #1f1f1f;
157 margin: 15px 0 0 0;
158 }
159
160 .badge {
161 display: none;
162 float: right;
163 margin: 18px 0 0 0;
164 width: 32px;
165 height: 20px;
166 background: #f00000;
167 color: white;
168 text-align: center;
169 -webkit-border-radius: 10px;
170 -moz-border-radius: 10px;
171 border-radius: 10px;
172 }
173
174 .badge span {
175 position: relative;
176 top: 1px;
177 font-size: 10px;
178 }
179
180 .chatpart {
181 float: right;
182 width: 526px;
183 border: 0px red solid;
184 background: #d7eaf3;
185 margin-top: -535px;
186 }
187
188 .msgflow {
189 width: 525px;
190 height: 380px;
191 border: 1px rgb(181, 178, 178) solid;
192 padding: 20px 6px 0 6px;
193 background: #f5f5f5;
194 overflow: auto;
195 }
196 .msgflow .onemsg{position:relative;}
197 .msgflow .onemsg .msghead {
198 color: green;
199 line-height: 12px;
200 font-size: 12px;
201 }
202
203 .msgflow .onemsg .msgbody {
204 margin: 0 0 0 18px;
205 line-height: 13px;
206 font-size: 14px;
207 }
208
209 .msgflow .msgbody img {
210 max-width: 500px;
211 }
212
213 .editbar {
214 width: 526px;
215 height: 25px;
216 }
217
218 .chat02_title_btn {
219 background: url('../img/icon.png') no-repeat 0 0;
220 cursor: pointer;
221 float: left;
222 display: block;
223 width: 15px;
224 height: 15px;
225 margin: 5px 6px;
226 }
227
228 .ctb01 {
229 background-position: 0 -90px;
230 margin-left: 18px;
231 _margin-left: 8px;
232 }
233
234 .ctb03 {
235 background-position: 0 -152px;
236 }
237
238 .ctb02 {
239 background-position: 0 -457px;
240 }
241
242 .ctb05 {
243 background-position: 0 -217px;
244 }
245
246 .ctb04 {
247 background-position: 0 -543px;
248 }
249
250 .wl_faces_box {
251 background: url('../img/wlf_bg.png') repeat 0 0;
252 position: relative;
253 /*position: absolute;*/
254 width: 428px;
255 height: 225px;
256 bottom: 220px;
257 left: -50px;
258 display: none;
259 }
260
261 .wl_faces_content {
262 background: #fff;
263 border: 1px #ccc solid;
264 width: 417px;
265 height: 216px;
266 margin: 3px 4px;
267 }
268
269 .wl_faces_content .title {
270 background: url('../img/wlf_title_bg.jpg') repeat-x 0 0;
271 height: 40px;
272 position: relative;
273 }
274
275 .wl_faces_content .title ul {
276
277 }
278
279 .wl_faces_content .title ul li {
280 position: absolute;
281 display: block;
282 }
283
284 .wl_faces_content .title ul li.title_name {
285 background: url('../img/wlf_title_btn.jpg') no-repeat 0 0;
286 width: 82px;
287 height: 30px;
288 bottom: 0;
289 _bottom: -2px;
290 left: 15px;
291 text-align: center;
292 line-height: 32px;
293 font-weight: bold;
294 color: #333;
295 }
296
297 .wl_faces_content .title ul li.wl_faces_close {
298 right: 8px;
299 top: 15px;
300 }
301
302 .wl_faces_content .title ul li.wl_faces_close span {
303 background: url('../img/icon.png') repeat-x 0 0;
304 cursor: pointer;
305 display: block;
306 width: 15px;
307 height: 15px;
308 }
309
310 .wl_faces_main {
311
312 }
313
314 .wl_faces_main ul {
315 margin: 12px 12px;
316 padding: 0px;
317 overflow: hidden;
318 border-top: 1px #CCC solid;
319 border-left: 1px #CCC solid;
320 list-style: none;
321 width: 393px;
322 }
323
324 .wl_faces_main ul li {
325 float: left;
326 border-right: 1px #CCC solid;
327 border-bottom: 1px #CCC solid;
328 height: 28px;
329 width: 28px;
330 margin: 0px 0px 0px 0px;
331 padding: 4px 2px;
332 text-align: center;
333 }
334
335 .wl_faces_main ul li img {
336 width: 24px;
337 height: 24px;
338 }
339
340 .wlf_icon {
341 background: url('../img/layer_arrow.png') no-repeat 0 0;
342 position: absolute;
343 width: 22px;
344 height: 9px;
345 bottom: -4px;
346 _bottom: -11px;
347 left: 61px;
348 }
349
350 .msgedit {
351 width: 525px;
352 height: 100px;
353 border: 1px rgb(181, 178, 178) solid;
354 background: #f5f5f5;
355 padding: 6px 6px;
356 line-height: 1.5;
357 }
358
359 .sendbar {
360 width: 526px;
361 height: 30px;
362 }
363
364 .sendbtn {
365 float: right;
366 width: 80px;
367 margin-right: 10px;
368 font: 10px/1.5 "微软雅黑";
369 }
370
371 .closebtn {
372 float: right;
373 width: 80px;
374 margin-right: 10px;
375 font: 10px/1.5 "微软雅黑";
376 }
377
378 .bottom {
379 clear: both;
380 height: 3px;
381 background: #d7eaf3;
382 }
383
384 #demo_type_desc {
385 display : none;
386 color: red;
387 }
388
389 #myself_type_desc {
390 /* display: none; */
391 color: red;
392 }
393
394 #qcloudLink {
395 color: blue;
396 }
397
398 #sdkAppIdDiv {
399 /* display: none; */
400 }
401
402 #accountTypeDiv {
403 /* display: none; */
404 }
405
406 .pic_thumb {
407 width: 200px;
408 height: 200px;
409 }
410
411
412
413 .spinner {
414 width: 60px;
415 text-align: center;
416 position: absolute;
417 right: 10px;
418 top: 32px;
419 text-align: right;
420 }
421
422 .spinner > div {
423 width: 6px;
424 height: 6px;
425 background-color: #333;
426
427 border-radius: 100%;
428 display: inline-block;
429 -webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
430 animation: sk-bouncedelay 1.4s infinite ease-in-out both;
431 }
432
433 .spinner .bounce1 {
434 -webkit-animation-delay: -0.32s;
435 animation-delay: -0.32s;
436 }
437
438 .spinner .bounce2 {
439 -webkit-animation-delay: -0.16s;
440 animation-delay: -0.16s;
441 }
442
443 @-webkit-keyframes sk-bouncedelay {
444 0%, 80%, 100% { -webkit-transform: scale(0) }
445 40% { -webkit-transform: scale(1.0) }
446 }
447
448 @keyframes sk-bouncedelay {
449 0%, 80%, 100% {
450 -webkit-transform: scale(0);
451 transform: scale(0);
452 } 40% {
453 -webkit-transform: scale(1.0);
454 transform: scale(1.0);
455 }
456 }
457
458 .headurlClass{
459 height: 30px;
460 width: 30px;
461 border-radius: 50%;
462 }
463
464 .delChat{
465 color: red;
466 width: 50px;
467 padding: 16px 0;
468 float: right;
469 margin-right: 5px;
470 }
...\ No newline at end of file ...\ No newline at end of file
1
2 本文主要介绍如何快速地将腾讯云 IM SDK 集成到您的 Web 项目中,只要按照如下步骤进行配置,就可以完成 SDK 的集成工作。
3
4
5 ## 准备工作
6 在集成 Web SDK 前,请确保您已完成以下步骤,请参见 [一分钟跑通 Demo](https://cloud.tencent.com/document/product/269/36838)
7 - 创建了腾讯云即时通信 IM 应用,并获取到 SDKAppID。
8 - 获取密钥信息。
9
10 ## 下载组件源码
11 您可以直接从 [Github](https://github.com/tencentyun/TIMSDK) 上下载 IM SDK H5 开发包。
12 SDK 存放路径为 TIMSDK/TIMSDK/H5/sdk/,相关文件清单如下:
13
14 | 目录| 说明 |
15 |:-------:|---------|
16 | json2.js | 提供了 JSON 的序列化和反序列化方法,可以将一个 JSON 对象转换成 JSON 字符串,也可以将一个 JSON 字符串转换成一个 JSON 对象,如果要需要在原生不支持 JSON 数据格式处理的浏览器使用 WEBIM SDK,则需要引入该文件 |
17 | spark-md5 | 用于获取文件 MD5,在上传图片时需要先获取文件的 MD5 |
18 | webim.js | WEBIM SDK 库,提供了聊天,群组管理,资料管理,关系链(好友,黑名单)管理功能 |
19
20 ## 集成 SDK
21 在需要实现 WEB IM 的页面引入 SDK 相关文件:
22 ```html
23 <script type="text/javascript" src="./sdk/json2.js"></script>
24 <!--用于获取文件MD5,上传图片需要先获取文件的 MD5-->
25 <script type="text/javascript" src="./sdk/spark-md5.js"></script>
26 <script type="text/javascript" src="./sdk/webim.js"></script>
27 ```
28
29 ## SDK 函数调用顺序
30
31 | 步骤 | 对应函数 | 说明 |
32 |---------|---------|---------|
33 | SDK 登录 | webim.login(loginInfo, listeners,opts,cbOk,cbErr);| 登录 SDK,需要传入当前用户信息,新消息通知回调函数等,注意,为了版本向下兼容,仍保留了老版本的初始化 init 接口,它和 login 是一样的,开发者调用其中一个即可。|
34 | 监听新消息|Demo 中使用的监听函数是 onMsgNotify(监听新消息)、groupSystemNotifys(监听群系统消息))|业务自定义监听函数,包括好友消息,群普通消息,群提示消息和群系统消息,登录时传给 SDK。 |
35 | 上报已读消息|webim.setAutoRead(selSess, isOn, isResetAll);|设置聊天会话自动已读标识。|
36 | 发消息 |webim.sendMsg(options,cbOk, cbErr); |发送消息(私聊和群聊)。 |
37 | 获取消息 |webim.getC2CHistoryMsgs (options,cbOk, cbErr);|获取好友历史消息。 |
38 | 获取消息 |webim.syncGroupMsgs(options,cbOk, cbErr);|获取群历史消息。 |
39 | 资料管理 |webim.getProfilePortrait(options,cbOk, cbErr);|查询个人资料。 |
40 | 资料管理 |webim.setProfilePortrait(options,cbOk, cbErr);|设置个人资料。 |
41 | 好友管理|webim.applyAddFriend(options,cbOk, cbErr);|申请添加好友。|
42 | 好友管理|webim.getAllFriend(options,cbOk, cbErr);等|获取我的好友等。|
43 | 群组管理|webim.createGroup(options,cbOk, cbErr);|创建群。|
44 | 群组管理|webim.applyJoinGroup(options,cbOk,cbErr);等|申请加群等。|
45 | SDK 登出|webim.logout(options,cbOk, cbErr); |退出,用于切换帐号登录。 |
46
47 ## 支持的平台
48 - IM SDK 支持 IE 7+ ( Windows XP / Vista 除外),Chrome 7+,FireFox 3.6+,Opera 12+ 和 Safari 6+。
49 - Demo 支持 IE 8+ ( Windows XP / Vista 除外),Chrome 7+,FireFox 3.6+,Opera 12+ 和 Safari 6+。
1 本文主要介绍如何快速地将腾讯云 IM SDK 集成到您的小程序项目中,只要按照如下步骤进行配置,就可以完成 SDK 的集成工作。
2 >! 当前小程序版本 Demo 仅提供直播聊天室场景。
3
4 ## 准备工作
5 在集成小程序 SDK 前,请确保您已完成以下步骤,请参见 [一分钟跑通 Demo](https://cloud.tencent.com/document/product/269/36838)
6 - 创建了腾讯云即时通信 IM 应用,并获取到 SDKAppID。
7 - 获取私钥文件。
8 - 小程序服务器域名配置。
9
10 ## 开发环境要求
11 - 最新版微信 Web 开发者工具。
12 - 小程序基础库最低版本要求:1.7.0。
13 - 微信 App iOS 最低版本要求:6.5.21。
14 - 微信 App Android 最低版本要求:6.5.19。
15
16 ## 下载组件源码
17 您可以直接从 [Github](https://github.com/tencentyun/TIMSDK) 上下载 IM SDK WXMini 开发包。
18 SDK 路径为 TIMSDK/WXMini/utils/webim_wx.js
19 ![](https://main.qcloudimg.com/raw/418f52960facd081c932cd34e77ce0a6.png)
20
21 ## 集成组件
22 将 webim_wx.js 拷贝到您的小程序项目里合适的目录下(例如 components 文件夹)。
23 详细的调用过程可参考小程序 Demo 源码。
24
25 ## 常见问题
26
27 ### 如果需要上线或者部署正式环境怎么办?
28 请将以下域名在 【微信公众平台】>【开发】>【开发设置】>【服务器域名】中进行配置,添加到 **request 合法域名**中:
29
30 | 域名 | 说明 | 是否必须 |
31 |:-------:|---------|----|
32 |`https://webim.tim.qq.com` | Web IM 业务域名 | 必须|
33 |`https://sxb.qcloud.com` | 测试 Demo 域名 | 非必须,使用测试 Demo 时配置|
1 ## 获取当前会话未读消息数
2
3 会话的未读记数存储在 `sessMap` 对象中,其结构描述 如下:
4 ```javascript
5 {
6 // 私聊会话,会话 ID skey 为'C2C[toAccount]',其中'[toAccount]'表示对方的帐号
7 // 例如您正在和 identifier 为 'zhangsan' 的帐号聊天,而 [toAccout]取值为'zhangsan'。
8 // 而'C2C[toAccount]'取值为'C2Czhangsan'
9 'C2C[toAccount]': {
10 // ...省略
11 id: '[toAccount]',
12 name: '[toAccount]',
13 unread: Function,
14 //... 省略
15 },
16
17 // 群聊会话,会话 ID skey 为'GROUP[groupId]',其中'[groupId]'表示群组 ID
18 // 例如您在群组 ID 为 'developergroup' 的群中聊天,此时[groupId]取值为'developergroup'。
19 // 而'GROUP[groupId]'取值为'GROPdevelopergroup'
20 'GROUP[groupId]': {
21 // ...省略
22 id: '[groupId]',
23 name: '[groupId]',
24 unread: Function,
25 //... 省略
26 }
27 }
28 ```
29
30 因此,获取某个会话的未读消息记数需要以下步骤:
31 1. 取得会话 ID : skey,skey 的组装规则:私聊 "C2C[toAccount]" ; 群组 "GROUP[groupId]"。
32 2. 取得`sessMap`对象,可以通过`webim.MsgStore.sessMap()`方法来取得`sessMap`对象。
33 3. 用调用`sessMap[skey].unread()`便可取得这个会话的未数消息计数。
34
35 ### 私聊场景示例
36
37 以与 identifier 为'zhangsan'的帐号私聊为例,示例如下:
38
39 ```javascript
40 var skey= 'C2Czhangsan'; // 拼装 skey
41 var sessMap = webim.MsgStore.sessMap(); // 获取 sessMap
42 sessMap[skey].unread(); // 获取未读消息记数
43 ```
44
45 ### 群聊场景示例
46
47 以群组 ID 为"developergroup"为例,示例如下:
48
49 ```javascript
50 var skey= 'GROUPdevelopergroup'; // 拼装 skey
51 var sessMap= webim.MsgStore.sessMap(); // 获取 sessMap
52 sessMap[skey].unread(); // 获取未读消息记数
53 ```
54
55 ## 设置会话自动已读标记
56
57 当用户阅读某个会话的数据后,需要进行会话消息的已读上报,IM SDK 根据会话中最后一条阅读的消息,设置会话中之前所有消息为已读。 函数原型如下:
58
59 ```javascript
60 /**
61 * 设置会设置会话自动已读标记话自动已读上报标志
62 * @param {Object} selSess - 会话对象,必须为 webim.Session 的实例。
63 * @param {boolean} isOn - 是否上报当前会话已读消息,同时将 selSess 的自动已读消息标志改为 isOn
64 * @param {boolean} isResetAll - 是否重置所有会话的自动已读标志
65 */
66 setAutoRead: function(selSess, isOn, isResetAll) {}
67 ```
68
69 `setAutoRead()`方法需要会话(Webim.Session)的实例为参数,所以应先获取会话实例,再把会话传递给`setAutoRead()`,步骤如下:
70 1. 获取会话实例。
71 2. 调用`setAutoRead()`
72
73 ### 私聊场景示例:
74
75 以与 identifier为'zhangsan'的帐号私聊为例,示例如下:
76
77 ```javascript
78 var skey= 'C2Czhangsan'; // 拼装 skey
79 var sessMap = webim.MsgStore.sessMap(); // 获取 sessMap
80 var selSess= sessMap[skey]; // 获取 Session 的实例
81 webim.setAutoRead(selSess, true, true);
82 ```
83
84
85
86 ### 群组场景示例:
87
88 以群组 ID 为"developergroup"为例,示例如下:
89
90 ```javascript
91 var skey= 'GRPUPdevelopergroup'; // 拼装 skey
92 var sessMap = webim.MsgStore.sessMap(); // 获取 sessMap
93 var selSess= sessMap[skey]; // 获取 Session 的实例
94 webim.setAutoRead(selSess, true, true);
95 ```
1 目前是通过定义好友系统消息监听事件来处理好友系统消息的。**示例:**
2
3 ```javascript
4 //监听好友系统通知函数对象,方法都定义在 receive_friend_system_msg.js 文件中
5 var onFriendSystemNotifys = {
6 "1": onFriendAddNotify, //好友表增加
7 "2": onFriendDeleteNotify, //好友表删除
8 "3": onPendencyAddNotify, //未决增加
9 "4": onPendencyDeleteNotify, //未决删除
10 "5": onBlackListAddNotify, //黑名单增加
11 "6": onBlackListDeleteNotify//黑名单删除
12 };
13 ```
14
15 ## 好友表添加
16
17 **触发时机:**当用户添加了新的好友时,会收到好友表添加通知。
18
19 **示例:**
20
21 ```javascript
22 //监听 好友表添加 系统通知
23 /*notify对数示例:
24 {
25 'Type':1,//通知类型
26 'Accounts':['jim','bob']//用户 ID 列表
27 }
28 */
29 function onFriendAddNotify(notify) {
30 webim.Log.info("执行 好友表添加 回调:"+JSON.stringify(notify));
31 //好友表发生变化,需要重新加载好友列表或者单独添加 notify.Accounts 好友帐号
32 getAllFriend(getAllFriendsCallbackOK);
33 var typeCh = "[好友表添加]";
34 var content = "新增以下好友:"+notify.Accounts;
35 addFriendSystemMsg(notify.Type, typeCh, content);
36 }
37 ```
38
39 ## 好友表删除
40
41 **触发时机:**当用户的好友发生减少时,会收到好友表删除通知。
42
43 **示例:**
44
45 ```javascript
46 //监听 好友表删除 系统通知
47 /*notify对数示例:
48 {
49 'Type':2,//通知类型
50 'Accounts':['jim','bob']//用户 ID 列表
51 }
52 */
53 function onFriendDeleteNotify(notify) {
54 webim.Log.info("执行 好友表删除 回调:"+JSON.stringify(notify));
55 //好友表发生变化,需要重新加载好友列表或者单独删除notify.Accounts好友帐号
56 getAllFriend(getAllFriendsCallbackOK);
57 var typeCh = "[好友表删除]";
58 var content = "减少以下好友:"+notify.Accounts;
59 addFriendSystemMsg(notify.Type, typeCh, content);
60 }
61 ```
62
63 ## 加好友未决添加
64
65 **触发时机:**当有人向您发出好友申请时,会收到加好友通知。
66
67 **示例: **
68
69 ```javascript
70 //监听 未决添加 系统通知
71 /*notify对象示例:
72 {
73 "Type":3,//通知类型
74 "PendencyList":[
75 {
76 "PendencyAdd_Account": "peaker1",//对方帐号
77 "ProfileImNic": "匹克1",//对方昵称
78 "AddSource": "AddSource_Type_Unknow",//来源
79 "AddWording": "您好"//申请附言
80 },
81 {
82 "PendencyAdd_Account": "peaker2",//对方帐号
83 "ProfileImNic": "匹克2",//对方昵称
84 "AddSource": "AddSource_Type_Unknow",//来源
85 "AddWording": "您好"//申请附言
86 }
87 ]
88 }
89 */
90 function onPendencyAddNotify(notify) {
91 webim.Log.info("执行 未决添加 回调:"+JSON.stringify(notify));
92 //收到加好友申请,弹出拉取好友申请列表
93 getPendency(true);
94 var typeCh = "[未决添加]";
95 var pendencyList=notify.PendencyList;
96 var content = "收到以下加好友申请:"+JSON.stringify(pendencyList);
97 addFriendSystemMsg(notify.Type, typeCh, content);
98 }
99 ```
100
101 ## 加好友未决删除
102
103 **触发时机:**当用户被管理员踢出群组时,用户会收到被踢出群的消息。
104
105 **示例:**
106
107 ```javascript
108 //监听 未决删除 系统通知
109 /*notify对数示例:
110 {
111 'Type':4,//通知类型
112 'Accounts':['jim','bob']//用户 ID 列表
113 }
114 */
115 function onPendencyDeleteNotify(notify) {
116 webim.Log.info("执行 未决删除 回调:"+JSON.stringify(notify));
117 var typeCh = "[未决删除]";
118 var content = "以下好友未决已被删除:"+notify.Accounts;
119 addFriendSystemMsg(notify.Type, typeCh, content);
120 }
121 ```
122
123 ## 好友黑名单添加
124
125 **触发时机:**当新增好友黑名单时,会收到此类通知。
126
127 **示例: **
128
129 ```javascript
130 //监听 好友黑名单添加 系统通知
131 /*notify对数示例:
132 {
133 'Type':5,//通知类型
134 'Accounts':['jim','bob']//用户 ID 列表
135 }
136 */
137 function onBlackListAddNotify(notify) {
138 webim.Log.info("执行 黑名单添加 回调:"+JSON.stringify(notify));
139 var typeCh = "[黑名单添加]";
140 var content = "新增以下黑名单:"+notify.Accounts;
141 addFriendSystemMsg(notify.Type, typeCh, content);
142 }
143 ```
144
145 ## 好友黑名单删除
146
147 **触发时机:**当删除好友黑名单时,会收到此类通知。
148
149 **示例: **
150
151 ```javascript
152 //监听 好友黑名单删除 系统通知
153 /*notify对数示例:
154 {
155 'Type':6,//通知类型
156 'Accounts':['jim','bob']//用户 ID 列表
157 }
158 */
159 function onBlackListDeleteNotify(notify) {
160 webim.Log.info("执行 黑名单删除 回调:"+JSON.stringify(notify));
161 var typeCh = "[黑名单删除]";
162 var content = "减少以下黑名单:"+notify.Accounts;
163 addFriendSystemMsg(notify.Type, typeCh, content);
164 }
165 ```
1 目前是通过定义资料系统消息监听事件来处理通知。**示例:**
2
3 ```javascript
4 //监听资料系统通知函数对象,方法都定义在 receive_profile_system_msg.js 文件中
5 var onProfileSystemNotifys = {
6 "1": onProfileModifyNotify//资料修改
7 };
8 ```
9
10 ## 资料变化
11
12 **触发时机:**当自己或好友的资料发生变化时,会收到此类通知。
13
14 **示例:**
15
16 ```javascript
17 //监听 资料变化(自己或好友) 系统通知
18 /*notify对数示例:
19 {
20 "Type":1,//子通知类型
21 "Profile_Account": "Jim",//用户帐号
22 "ProfileList": [
23 {
24 "Tag": "Tag_Profile_IM_Nick",//昵称
25 "ValueBytes": "吉姆"
26 },
27 {
28 "Tag": "Tag_Profile_IM_Gender",//性别
29 "ValueBytes": "Gender_Type_Male"
30 },
31 {
32 "Tag": "Tag_Profile_IM_AllowType",//加好友认证方式
33 "ValueBytes": "AllowType_Type_NeedConfirm"
34 }
35 ]
36 }
37 */
38 function onProfileModifyNotify(notify) {
39 webim.Log.info("执行 资料修改 回调:"+JSON.stringify(notify));
40 var typeCh = "[资料修改]";
41 var profile,account,nick,sex,allowType,content;
42 account=notify.Profile_Account;
43 content = "帐号:"+account+", ";
44 for(var i in notify.ProfileList){
45 profile=notify.ProfileList[i];
46 switch(profile.Tag){
47 case 'Tag_Profile_IM_Nick':
48 nick=profile.ValueBytes;
49 break;
50 case 'Tag_Profile_IM_Gender':
51 sex=profile.ValueBytes;
52 break;
53 case 'Tag_Profile_IM_AllowType':
54 allowType=profile.ValueBytes;
55 break;
56 default:
57 webim.log.error('未知资料字段:'+JSON.stringify(profile));
58 break;
59 }
60 }
61 content+="最新资料:【昵称】:"+nick+",【性别】:"+sex+",【加好友方式】:"+allowType;
62 addProfileSystemMsg(notify.Type, typeCh, content);
63 if(account!=loginInfo.identifier){//如果是好友资料更新
64 //好友资料发生变化,需要重新加载好友列表或者单独更新 account 的资料信息
65 getAllFriend(getAllFriendsCallbackOK);
66 }
67 }
68 ```
...\ No newline at end of file ...\ No newline at end of file
1
2 **登出 `logout` 函数名:**
3
4 ```
5 webim.logout
6 ```
7
8 **定义:**
9
10 ```
11 webim.logout(cbOk, cbErr)
12 ```
13
14 **参数列表:**
15
16 | 名称 | 说明 | 类型 |
17 |---------|---------|---------|
18 |cbOk |调用接口成功回调函数 |Function|
19 |cbErr |调用接口失败回调函数 |Function|
20
21 **示例:**
22
23 ```javascript
24 //登出
25 function quitClick() {
26 if (loginInfo.identifier) {
27 //SDK 登出
28 webim.logout(
29 function (resp) {
30 loginInfo.identifier = null;
31 loginInfo.userSig = null;
32 document.getElementById("webim_demo").style.display = "none";
33 var indexUrl = window.location.href;
34 var pos = indexUrl.indexOf('?');
35 if (pos >= 0) {
36 indexUrl = indexUrl.substring(0, pos);
37 }
38 window.location.href = indexUrl;
39 }
40 );
41 } else {
42 alert('未登录');
43 }
44 }
45 ```
1
2 **`logout` 函数名:**
3
4 ```
5 webim.logout
6 ```
7
8 **定义:**
9
10 ```
11 webim.logout(cbOk, cbErr)
12 ```
13
14 **参数列表:**
15
16 | 名称 | 说明 | 类型 |
17 |---------|---------|---------|
18 |cbOk |调用接口成功回调函数 |Function|
19 |cbErr |调用接口失败回调函数 |Function|
20
21 **示例:**
22
23 ```
24 //登出
25 function logout() {
26 //登出
27 webim.logout(
28 function (resp) {
29 webim.Log.info('登出成功');
30 loginInfo.identifier = null;
31 loginInfo.userSig = null;
32 $("#video_sms_list").find("li").remove();
33 var indexUrl = window.location.href;
34 var pos = indexUrl.indexOf('?');
35 if (pos >= 0) {
36 indexUrl = indexUrl.substring(0, pos);
37 }
38 window.location.href = indexUrl;
39 }
40 );
41 }
42 ```
1 ## 获取群成员列表
2
3 ```javascript
4 /* function getGroupMemberInfo
5 * 获取群组成员列表
6 * params:
7 * options - 请求参数
8 * cbOk - function()类型, 成功时回调函数
9 * cbErr - function(err)类型, 失败时回调函数, err 为错误对象
10 * return:
11 * (无)
12 */
13 getGroupMemberInfo: function(options, cbOk, cbErr) {},
14 ```
15
16 >?详细参数说明请参考 [获取群组成员详细资料 API](https://cloud.tencent.com/document/product/269/1617)。
17
18 **示例: **
19
20 ```javascript
21 //读取群组成员
22 var getGroupMemberInfo = function (group_id) {
23 initGetGroupMemberTable([]);
24 var options = {
25 'GroupId': group_id,
26 'Offset': 0, //必须从 0 开始
27 'Limit': totalCount,
28 'MemberInfoFilter': [
29 'Account',
30 'Role',
31 'JoinTime',
32 'LastSendMsgTime',
33 'ShutUpUntil'
34 ]
35 };
36 webim.getGroupMemberInfo(
37 options,
38 function (resp) {
39 if (resp.MemberNum <= 0) {
40 alert('该群组目前没有成员');
41 return;
42 }
43 var data = [];
44 for (var i in resp.MemberList) {
45 var account = resp.MemberList[i].Member_Account;
46 var role = webim.Tool.groupRoleEn2Ch(resp.MemberList[i].Role);
47 var join_time = webim.Tool.formatTimeStamp(
48 resp.MemberList[i].JoinTime);
49 var shut_up_until = webim.Tool.formatTimeStamp(
50 resp.MemberList[i].ShutUpUntil);
51 if (shut_up_until == 0) {
52 shut_up_until = '-';
53 }
54 data.push({
55 GroupId: group_id,
56 Member_Account: account,
57 Role: role,
58 JoinTime: join_time,
59 ShutUpUntil: shut_up_until
60 });
61 }
62 $('#get_group_member_table').bootstrapTable('load', data);
63 $('#get_group_member_dialog').modal('show');
64 },
65 function (err) {
66 alert(err.ErrorInfo);
67 }
68 );
69 };
70 ```
71
72 ## 邀请好友加群
73
74 ```javascript
75 /* function addGroupMember
76 * 邀请好友加群
77 * params:
78 * options - 请求参数
79 * cbOk - function()类型, 成功时回调函数
80 * cbErr - function(err)类型, 失败时回调函数, err 为错误对象
81 * return:
82 * (无)
83 */
84 addGroupMember: function(options, cbOk, cbErr) {},
85 ```
86
87 >?详细参数说明请参考 [增加群组成员 API](https://cloud.tencent.com/document/product/269/1621)。
88
89 **示例: **
90
91 ```javascript
92 //邀请好友加群
93 var addGroupMember = function () {
94 var options = {
95 'GroupId': $('#agm_group_id').val(),
96 'MemberList': [
97 {
98 'Member_Account': $('#agm_account').val()
99 }
100
101 ]
102 };
103 webim.addGroupMember(
104 options,
105 function (resp) {
106 //在表格中删除对应的行
107 $('#get_my_friend_group_table').bootstrapTable('remove', {
108 field: 'Info_Account',
109 values: [$('#agm_account').val()]
110 });
111 $('#add_group_member_dialog').modal('hide');
112 alert('邀请好友加群成功');
113 },
114 function (err) {
115 alert(err.ErrorInfo);
116 }
117 );
118 };
119 ```
120
121 ## 修改群消息提示
122
123 ```javascript
124 /* function modifyGroupMember
125 * 修改群成员资料(角色或者群消息提类型示)
126 * params:
127 * options - 请求参数
128 * cbOk - function()类型, 成功时回调函数
129 * cbErr - function(err)类型, 失败时回调函数, err 为错误对象
130 * return:
131 * (无)
132 */
133 modifyGroupMember: function(options, cbOk, cbErr) {},
134 ```
135
136 >?详细参数说明请参考 [修改群成员资料 API](https://cloud.tencent.com/document/product/269/1623)。
137
138 **示例: **
139
140 ```javascript
141 //修改群消息提示类型
142 var modifyGroupMsgFlag = function () {
143 var msg_flag_en = $('input[name="mgmf_msg_flag_radio"]:checked').val();
144 var msg_flag_zh = webim.Tool.groupMsgFlagEn2Ch(msg_flag_en);
145 var options = {
146 'GroupId': $('#mgmf_group_id').val(),
147 'Member_Account': loginInfo.identifier,
148 'MsgFlag': msg_flag_en
149 };
150 webim.modifyGroupMember(
151 options,
152 function (resp) {
153 //在表格中修改对应的行
154 $('#get_my_group_table').bootstrapTable('updateRow', {
155 index: $('#mgmf_sel_row_index').val(),
156 row: {
157 MsgFlag: msg_flag_zh,
158 MsgFlagEn: msg_flag_en
159 }
160 });
161 $('#modify_group_msg_flag_dialog').modal('hide');
162 alert('设置群消息提示类型成功');
163 },
164 function (err) {
165 alert(err.ErrorInfo);
166 }
167 );
168 };
169 ```
170
171 ## 修改群成员角色
172
173 ```javascript
174 /* function modifyGroupMember
175 * 修改群成员资料(角色或者群消息提类型示)
176 * params:
177 * options - 请求参数
178 * cbOk - function()类型, 成功时回调函数
179 * cbErr - function(err)类型, 失败时回调函数, err 为错误对象
180 * return:
181 * (无)
182 */
183 modifyGroupMember: function(options, cbOk, cbErr) {},
184 ```
185
186 >?详细参数说明请参考 [修改群成员资料 API](https://cloud.tencent.com/document/product/269/1623)。
187
188 **示例: **
189
190 ```javascript
191 //修改群组成员角色
192 var modifyGroupMemberRole = function () {
193 var role_en = $('input[name="mgm_role_radio"]:checked').val();
194 var role_zh = webim.Tool.groupRoleEn2Ch(role_en);
195 var options = {
196 'GroupId': $('#mgm_group_id').val(),
197 'Member_Account': $('#mgm_account').val(),
198 'Role': role_en
199 };
200 webim.modifyGroupMember(
201 options,
202 function (resp) {
203 //在表格中修改对应的行
204 $('#get_group_member_table').bootstrapTable('updateRow', {
205 index: $('#mgm_sel_row_index').val(),
206 row: {
207 Role: role_zh
208 }
209 });
210 $('#modify_group_member_dialog').modal('hide');
211 alert('修改群成员角色成功');
212 },
213 function (err) {
214 alert(err.ErrorInfo);
215 }
216 );
217 };
218 ```
219
220 ## 设置群成员禁言时间
221
222 ```javascript
223 /* function forbidSendMsg
224 * 设置群成员禁言时间
225 * params:
226 * options - 请求参数
227 * cbOk - function()类型, 成功时回调函数
228 * cbErr - function(err)类型, 失败时回调函数, err 为错误对象
229 * return:
230 * (无)
231 */
232 forbidSendMsg: function(options, cbOk, cbErr) {},
233 ```
234
235 >?详细参数说明请参考 [批量禁言和取消禁言 API](https://cloud.tencent.com/document/product/269/1627)。
236
237 **示例:**
238
239 ```javascript
240 //设置成员禁言时间
241 var forbidSendMsg = function () {
242 if (!webim.Tool.validNumber($('#fsm_shut_up_time').val())) {
243 alert('您输入的禁言时间非法,只能是数字(0-31536000)');
244 return;
245 }
246 var shut_up_time = parseInt($('#fsm_shut_up_time').val());
247 if (shut_up_time > 31536000) {
248 alert('您输入的禁言时间非法,只能是数字(0-31536000)');
249 return;
250 }
251 var shut_up_until = '-';
252 if (shut_up_time != 0) {
253 //当前时间+禁言时间=禁言截至时间
254 shut_up_until = webim.Tool.formatTimeStamp(
255 Math.round(new Date().getTime() / 1000) + shut_up_time);
256 }
257 var options = {
258 'GroupId': $('#fsm_group_id').val(),//群组id
259 'Members_Account': [$('#fsm_account').val()],//被禁言的成员帐号列表
260 'ShutUpTime': shut_up_time//禁言时间,单位:秒
261 };
262 webim.forbidSendMsg(
263 options,
264 function (resp) {
265 //在表格中修改对应的行
266 $('#get_group_member_table').bootstrapTable('updateRow', {
267 index: $('#fsm_sel_row_index').val(),
268 row: {
269 ShutUpUntil: shut_up_until
270 }
271 });
272 $('#forbid_send_msg_dialog').modal('hide');
273 alert('设置成员禁言时间成功');
274 },
275 function (err) {
276 alert(err.ErrorInfo);
277 }
278 );
279 };
280 ```
281
282 ## 删除群成员
283
284 ```javascript
285 /* function deleteGroupMember
286 * 删除群成员
287 * params:
288 * options - 请求参数
289 * cbOk - function()类型, 成功时回调函数
290 * cbErr - function(err)类型, 失败时回调函数, err 为错误对象
291 * return:
292 * (无)
293 */
294 deleteGroupMember: function(options, cbOk, cbErr) {},
295 ```
296
297 >?详细参数说明请参考 [删除群组成员 API](https://cloud.tencent.com/document/product/269/1622)。
298
299 **示例:**
300
301 ```javascript
302 //删除群组成员
303 var deleteGroupMember = function () {
304 if (!confirm("确定移除该成员吗?")) {
305 return;
306 }
307 var options = {
308 'GroupId': $('#dgm_group_id').val(),
309 //'Silence': $('input[name="dgm_silence_radio"]:checked').val(),
310 //只有 ROOT 用户采用权限设置该字段(是否静默移除)
311 'MemberToDel_Account': [$('#dgm_account').val()]
312 };
313 webim.deleteGroupMember(
314 options,
315 function (resp) {
316 //在表格中删除对应的行
317 $('#get_group_member_table').bootstrapTable('remove', {
318 field: 'Member_Account',
319 values: [$('#dgm_account').val()]
320 });
321 $('#delete_group_member_dialog').modal('hide');
322 alert('移除群成员成功');
323 },
324 function (err) {
325 alert(err.ErrorInfo);
326 }
327 );
328 };
329 ```
1
2
3 当有用户申请加群等事件发生时,管理员会收到邀请加群系统消息,相应的消息会通过群系统消息展示给用户。目前支持自动拉取群系统消息。
4
5 ## 监听群系统消息
6
7 **定义监听群系统消息示例:**
8
9 ```
10 //监听(多终端同步)群系统消息事件
11 var groupSystemNotifys = {
12 "1": onApplyJoinGroupRequestNotify, //申请加群请求(只有管理员会收到,不支持)
13 "2": onApplyJoinGroupAcceptNotify, //申请加群被同意(只有申请人能够收到,不支持)
14 "3": onApplyJoinGroupRefuseNotify, //申请加群被拒绝(只有申请人能够收到,不支持)
15 "4": onKickedGroupNotify, //被管理员踢出群(只有被踢者接收到,不支持)
16 "5": onDestoryGroupNotify, //群被解散(全员接收,支持)
17 "6": onCreateGroupNotify, //创建群(创建者接收,不支持)
18 "7": onInvitedJoinGroupNotify, //邀请加群(被邀请者接收,不支持)
19 "8": onQuitGroupNotify, //主动退群(主动退出者接收,不支持)
20 "9": onSetedGroupAdminNotify, //设置管理员(被设置者接收,不支持)
21 "10": onCanceledGroupAdminNotify, //取消管理员(被取消者接收,不支持)
22 "11": onRevokeGroupNotify, //群已被回收(全员接收,支持)
23 "255": onCustomGroupNotify//用户自定义通知(默认全员接收,支持)
24 };
25 ```
26
27 **显示群系统消息示例:**
28
29 ```
30 //显示一条群组系统消息
31 function showGroupSystemMsg(type, typeCh, group_id, group_name, msg_content, msg_time) {
32 var sysMsgStr="收到一条群系统消息: type="+type+", typeCh="+typeCh+",群ID="+group_id+", 群名称="+group_name+", 内容="+msg_content+", 时间="+webim.Tool.formatTimeStamp(msg_time);
33 webim.Log.warn(sysMsgStr);
34 alert(sysMsgStr);
35 }
36 ```
37
38 ## 监听群被解散消息
39
40 **触发时机:**当群被解散时,全员会收到解散群消息。支持全员接收消息。
41
42 **示例:**
43
44 ```
45 //监听 解散群 系统消息
46 function onDestoryGroupNotify(notify) {
47 webim.Log.warn("执行 解散群 回调:"+JSON.stringify(notify));
48 var reportTypeCh = "[群被解散]";
49 var content = "群主" + notify.Operator_Account + "已解散该群";
50 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
51 }
52 ```
53
54
55 ## 监听群被回收消息
56
57 **触发时机:**当有用户申请加群时,群管理员会收到申请加群消息,管理员决定是否同意对方加群。支持全员接收消息。
58
59 **示例:**
60
61 ```
62 //监听 群被回收 系统消息
63 function onRevokeGroupNotify(notify) {
64 webim.Log.warn("执行 群被回收 回调:"+JSON.stringify(notify));
65 var reportTypeCh = "[群被回收]";
66 var content = "该群已被回收";
67 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
68 }
69 ```
70
71 ## 监听自定义群通知消息
72
73 **触发时机:**当 App 管理员通过控制台发出自定义的系统消息时,全员可收到该消息。支持全员接收消息。
74
75 **示例:**
76
77 ```
78 //监听用户自定义群系统消息
79 function onCustomGroupNotify(notify) {
80 webim.Log.warn("执行 用户自定义系统消息 回调:"+JSON.stringify(notify));
81 var reportTypeCh = "[用户自定义系统消息]";
82 var content = notify.UserDefinedField;//群自定义消息数据
83 showGroupSystemMsg(notify.ReportType, reportTypeCh, notify.GroupId, notify.GroupName, content, notify.MsgTime);
84 }
85 ```
1
2 ## 进群
3
4 **`applyJoinBigGroup` 函数名:**
5
6 ```
7 webim.applyJoinBigGroup
8 ```
9
10 **定义:**
11
12 ```
13 webim.applyJoinBigGroup(options,cbOk, cbErr)
14 ```
15
16 **参数列表:**
17
18 | 名称 | 说明 | 类型 |
19 |---------|---------|---------|
20 |options| 进群信息对象| Object|
21 |cbOk |调用接口成功回调函数 |Function|
22 |cbErr |调用接口失败回调函数 |Function|
23
24 **其中 `options` 对象属性定义如下:**
25
26 | 名称 | 说明 | 类型 |
27 |---------|---------|---------|
28 |GroupId |要加入的群 ID |String|
29
30 **示例:**
31
32 ```
33 //加入直播大群
34 function applyJoinBigGroup(groupId) {
35 var options = {
36 'GroupId': groupId//群 ID
37 };
38 webim.applyJoinBigGroup(
39 options,
40 function (resp) {
41 //JoinedSuccess:加入成功; WaitAdminApproval:等待管理员审批
42 if (resp.JoinedStatus && resp.JoinedStatus == 'JoinedSuccess') {
43 webim.Log.info('加入房间成功');
44 } else {
45 alert('加入房间失败');
46 }
47 },
48 function (err) {
49 alert(err.ErrorInfo);
50 }
51 );
52 }
53 ```
54
55 ## 退群
56
57 **`quitBigGroup` 函数名:**
58
59 ```
60 webim.quitBigGroup
61 ```
62
63 **定义:**
64
65 ```
66 webim.quitBigGroup(options,cbOk, cbErr)
67 ```
68
69 **参数列表:**
70
71 | 名称 | 说明 | 类型 |
72 |---------|---------|---------|
73 |options |退群信息对象 |Object|
74 |cbOk |调用接口成功回调函数 |Function|
75 |cbErr |调用接口失败回调函数 |Function|
76
77 **其中 `options` 对象属性定义如下:**
78
79 | 名称 | 说明 | 类型 |
80 |---------|---------|---------|
81 |GroupId|要退出的群 ID |String|
82
83 **示例:**
84
85 ```
86 //退出大群
87 function quitBigGroup() {
88 var options = {
89 'GroupId': avChatRoomId//群 ID
90 };
91 webim.quitBigGroup(
92 options,
93 function (resp) {
94 webim.Log.info('退群成功');
95 $("#video_sms_list").find("li").remove();
96 },
97 function (err) {
98 alert(err.ErrorInfo);
99 }
100 );
101 }
102 ```
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
No preview for this file type
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.