Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
foreign
/
customer-service
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
03c9c8d6
authored
Jul 13, 2021
by
panjiangyi
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
格式化代码
parent
342401e1
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
501 additions
and
456 deletions
chat-list.vue
chat-room.vue
chat.vue
components/file-icon.vue
components/image-preview.vue
components/message.vue
components/video-player-icon.vue
components/video-preview.vue
components/voice.vue
components/who-read-list.vue
hybrid-input/index.vue
message-input.vue
message-list.vue
store/index.ts
third-party/image/index.ts
utils/jwt/index.ts
xim/index.ts
xim/logger.ts
xim/models/user.ts
xim/token.ts
xim/xim.ts
chat-list.vue
View file @
03c9c8d6
...
...
@@ -71,25 +71,26 @@
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
,
Prop
,
Watch
}
from
"vue-property-decorator"
import
{
chatStore
,
ChatStore
}
from
"@/customer-service/store/model"
import
buttonThrottle
from
"@/utils/button-throttle"
;
import
{
Component
,
Prop
,
Vue
}
from
"vue-property-decorator"
;
import
{
chatStore
,
ChatStore
}
from
"@/customer-service/store/model"
;
// import { popupService } from "@/views/common-module/component/element-upgrades/fast-service-popup";
import
buttonThrottle
from
"@/utils/button-throttle"
import
Chat
from
"@/customer-service/xim"
import
{
formatTime
,
TimeFormatRule
}
from
"@/customer-service/utils/time"
import
{
formatTime
,
TimeFormatRule
}
from
"@/customer-service/utils/time"
;
import
Chat
from
"@/customer-service/xim"
;
export
function
parserMessage
(
type
:
string
,
rawMsg
:
string
)
{
if
(
!
type
)
return
""
if
(
!
rawMsg
)
return
""
const
msg
=
JSON
.
parse
(
rawMsg
)
if
(
!
type
)
return
""
;
if
(
!
rawMsg
)
return
""
;
const
msg
=
JSON
.
parse
(
rawMsg
)
;
if
(
type
===
"text"
)
{
return
msg
.
text
return
msg
.
text
;
}
else
if
(
type
===
"image"
)
{
return
`[图片]`
return
`[图片]`
;
}
else
if
(
type
===
"file"
)
{
return
`[文件]`
return
`[文件]`
;
}
else
{
;
`[不支持的消息格式]`
return
`[不支持的消息格式]`
;
}
}
type
Chat
=
ChatStore
.
STATE_MY_CHAT_ROOM_LIST
[
"list"
][
number
]
...
...
@@ -101,8 +102,10 @@ export default class ChatList extends Vue {
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
)
private
readonly
chatId
!
:
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID
)
private
readonly
currentChatUniplatId
!
:
ChatStore
.
STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_CHAT_VERSION
)
private
readonly
uniplatVersion
!
:
ChatStore
.
STATE_CHAT_CURRENT_CHAT_VERSION
...
...
@@ -127,58 +130,58 @@ export default class ChatList extends Vue {
private
searchKeyword
=
""
private
get
chatRooms
()
{
return
this
.
chatList
?.
list
||
[]
return
this
.
chatList
?.
list
||
[]
;
}
private
isSelected
(
item
:
Chat
)
{
if
(
this
.
currentChatUniplatId
)
{
return
item
.
uniplatId
===
this
.
currentChatUniplatId
return
item
.
uniplatId
===
this
.
currentChatUniplatId
;
}
return
this
.
selected
===
item
.
uniplatId
return
this
.
selected
===
item
.
uniplatId
;
}
async
created
()
{
await
this
.
getMyChatList
()
this
.
setSource
(
ChatStore
.
StateChatSourceDirection
.
Server
)
this
.
selectFirstChat
()
await
this
.
getMyChatList
()
;
this
.
setSource
(
ChatStore
.
StateChatSourceDirection
.
Server
)
;
this
.
selectFirstChat
()
;
}
mounted
()
{
this
.
saveMyId
()
this
.
goToOnlyRoom
()
this
.
saveMyId
()
;
this
.
goToOnlyRoom
()
;
}
private
goToOnlyRoom
()
{
if
(
this
.
chatRooms
.
length
===
1
)
{
const
wantedChat
=
this
.
chatRooms
[
0
]
this
.
goToChatRoom
(
wantedChat
)
const
wantedChat
=
this
.
chatRooms
[
0
]
;
this
.
goToChatRoom
(
wantedChat
)
;
}
}
private
selectFirstChat
()
{
if
(
this
.
chatId
!=
null
)
return
if
(
!
this
.
chatRooms
.
length
)
return
const
{
chat_id
,
uniplat_version
,
uniplatId
}
=
this
.
chatRooms
[
0
]
if
(
this
.
chatId
!=
null
)
return
;
if
(
!
this
.
chatRooms
.
length
)
return
;
const
{
chat_id
,
uniplat_version
,
uniplatId
}
=
this
.
chatRooms
[
0
]
;
this
.
saveChatId
({
chatId
:
chat_id
,
v
:
uniplat_version
,
uniplatId
,
})
})
;
}
@
buttonThrottle
()
private
async
search
()
{
this
.
searchKeyword
=
this
.
searchKeyword
.
trim
()
this
.
searchKeyword
=
this
.
searchKeyword
.
trim
()
;
if
(
!
this
.
searchKeyword
)
{
await
this
.
getMyChatList
()
await
this
.
getMyChatList
()
;
}
else
{
await
this
.
getMyChatList
(
this
.
searchKeyword
)
await
this
.
getMyChatList
(
this
.
searchKeyword
)
;
}
}
private
goToChatRoom
(
data
:
Chat
)
{
if
(
this
.
currentChatUniplatId
===
data
.
uniplatId
)
{
return
return
;
}
this
.
saveChatId
({
...
...
@@ -186,21 +189,21 @@ export default class ChatList extends Vue {
.
chat_id
,
v
:
data
.
uniplat_version
,
uniplatId
:
data
.
uniplatId
,
}).
finally
(
this
.
raiseChatIdChanged
)
}).
finally
(
this
.
raiseChatIdChanged
)
;
this
.
saveChatTitle
(
data
.
uniplatId
)
this
.
saveChatTitle
(
data
.
uniplatId
)
;
}
private
raiseChatIdChanged
()
{
this
.
$emit
(
"change"
)
this
.
$emit
(
"change"
)
;
}
private
parseMesage
(
data
:
Chat
)
{
return
parserMessage
(
data
.
msg_type
,
data
.
msg
)
return
parserMessage
(
data
.
msg_type
,
data
.
msg
)
;
}
private
formatTimestamp
(
v
:
number
)
{
return
formatTime
(
v
,
{
short
:
true
,
rule
:
TimeFormatRule
.
Hour12
})
return
formatTime
(
v
,
{
short
:
true
,
rule
:
TimeFormatRule
.
Hour12
})
;
}
}
</
script
>
...
...
chat-room.vue
View file @
03c9c8d6
...
...
@@ -86,17 +86,18 @@
<
script
lang=
"ts"
>
import
{
Component
,
Watch
,
Vue
,
Ref
,
Provide
,
Prop
,
}
from
"vue-property-decorator"
import
MessageInput
from
"@/customer-service/message-input.vue"
import
messages
from
"@/customer-service/message-list.vue"
Provide
,
Ref
,
Vue
,
Watch
,
}
from
"vue-property-decorator"
;
import
MessageInput
from
"@/customer-service/message-input.vue"
;
import
messages
from
"@/customer-service/message-list.vue"
;
// import CusomterInfo from "./customer-info.vue"
// import OrderInfo from "./order-info.vue"
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
;
type
RoomInfoTab
=
"customer"
|
"order"
...
...
@@ -114,25 +115,31 @@ export default class ChatRoom extends Vue {
@
chatStore
.
Mutation
(
ChatStore
.
MUTATION_CLEAR_CURRENT_CHAT_MEMBERS
)
private
readonly
clearChatMembers
!
:
ChatStore
.
MUTATION_CLEAR_CURRENT_CHAT_MEMBERS
@
chatStore
.
State
(
ChatStore
.
STATE_CURRENT_CHAT_TITLE
)
private
readonly
chatTitle
!
:
ChatStore
.
STATE_CURRENT_CHAT_TITLE
@
chatStore
.
State
(
ChatStore
.
STATE_CURRENT_CHAT_INPUTING
)
private
readonly
currentInputPeople
!
:
ChatStore
.
STATE_CURRENT_CHAT_INPUTING
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID
)
private
readonly
currentChatUniplatId
!
:
ChatStore
.
STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID
@
chatStore
.
State
(
ChatStore
.
STATE_MY_CHAT_ROOM_LIST
)
private
readonly
myChatList
!
:
ChatStore
.
STATE_MY_CHAT_ROOM_LIST
private
allChatList
=
{
list
:
[]
}
@
Prop
({
type
:
Function
})
private
close
?:
()
=>
void
@
Provide
()
showReadSummary
=
true
@
Watch
(
"currentChatUniplatId"
)
private
whenCurrentChatIdChanged
(
newValue
:
string
,
oldValue
:
string
)
{
if
(
Number
(
oldValue
)
===
Number
(
newValue
))
return
this
.
hideMembers
()
this
.
clearChatMembers
()
if
(
Number
(
oldValue
)
===
Number
(
newValue
))
return
;
this
.
hideMembers
()
;
this
.
clearChatMembers
()
;
}
private
activeTab
:
RoomInfoTab
=
"customer"
...
...
@@ -141,38 +148,41 @@ export default class ChatRoom extends Vue {
private
get
getCurrentInputingPeople
()
{
return
this
.
currentInputPeople
.
map
((
k
)
=>
""
/* this.userInfo[k].name */
)
.
join
(
"、"
)
.
join
(
"、"
)
;
}
private
get
currentChat
()
{
const
chatId
=
this
.
currentChatUniplatId
let
result
=
this
.
myChatList
.
list
.
find
((
k
)
=>
k
.
uniplatId
===
chatId
)
if
(
result
)
return
result
result
=
this
.
allChatList
.
list
.
find
((
k
)
=>
k
.
uniplatId
===
chatId
)
return
result
??
{}
const
chatId
=
this
.
currentChatUniplatId
;
let
result
=
this
.
myChatList
.
list
.
find
((
k
)
=>
k
.
uniplatId
===
chatId
)
;
if
(
result
)
return
result
;
result
=
this
.
allChatList
.
list
.
find
((
k
)
=>
k
.
uniplatId
===
chatId
)
;
return
result
??
{}
;
}
private
get
notOnlyCheck
():
boolean
{
return
true
return
true
;
}
private
get
customerInfoTabShow
()
{
return
this
.
activeTab
===
"customer"
return
this
.
activeTab
===
"customer"
;
}
private
get
orderInfoTabShow
()
{
return
this
.
activeTab
===
"order"
return
this
.
activeTab
===
"order"
;
}
private
showMembers
()
{
this
.
membersPanelVisibility
=
!
this
.
membersPanelVisibility
this
.
membersPanelVisibility
=
!
this
.
membersPanelVisibility
;
}
private
hideMembers
()
{
this
.
membersPanelVisibility
=
false
this
.
membersPanelVisibility
=
false
;
}
private
onError
(
msg
:
string
)
{
console
.
error
(
msg
)
this
.
$message
.
error
(
msg
)
// eslint-disable-next-line no-console
console
.
error
(
msg
);
this
.
$message
.
error
(
msg
);
}
}
</
script
>
...
...
chat.vue
View file @
03c9c8d6
...
...
@@ -19,11 +19,13 @@
</el-dialog>
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
}
from
"vue-property-decorator"
import
MessageList
from
"./message-list.vue"
import
ChatRoom
from
"./chat-room.vue"
import
ChatList
from
"./chat-list.vue"
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
import
{
Component
,
Vue
}
from
"vue-property-decorator"
;
import
ChatList
from
"./chat-list.vue"
;
import
ChatRoom
from
"./chat-room.vue"
;
import
MessageList
from
"./message-list.vue"
;
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
;
@
Component
({
components
:
{
MessageList
,
ChatRoom
,
ChatList
}
})
export
default
class
Chat
extends
Vue
{
...
...
@@ -32,13 +34,15 @@ export default class Chat extends Vue {
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_DIALOG_VISIBLE
)
private
readonly
visible
:
ChatStore
.
STATE_CHAT_DIALOG_VISIBLE
@
chatStore
.
Mutation
(
ChatStore
.
MUTATION_HIDE_CHAT
)
private
readonly
hide
:
ChatStore
.
MUTATION_HIDE_CHAT
@
chatStore
.
Action
(
ChatStore
.
ACTION_TERINATE_CHAT
)
private
readonly
_terminate
:
ChatStore
.
ACTION_TERINATE_CHAT
private
terminate
()
{
this
.
_terminate
()
this
.
_terminate
()
;
}
}
</
script
>
...
...
components/file-icon.vue
View file @
03c9c8d6
...
...
@@ -3,9 +3,10 @@
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
}
from
"vue-property-decorator"
import
{
Model
}
from
"vue-property-decorator"
import
{
FileType
,
getSvg
}
from
"./file-controller"
import
{
Component
,
Model
,
Vue
}
from
"vue-property-decorator"
;
import
{
FileType
,
getSvg
}
from
"./file-controller"
;
@
Component
({
components
:
{}
})
export
default
class
FileIcon
extends
Vue
{
...
...
@@ -13,55 +14,55 @@ export default class FileIcon extends Vue {
private
value
!
:
FileType
private
get
audio
()
{
return
this
.
value
===
FileType
.
Audio
return
this
.
value
===
FileType
.
Audio
;
}
private
get
excel
()
{
return
this
.
value
===
FileType
.
Excel
return
this
.
value
===
FileType
.
Excel
;
}
private
get
image
()
{
return
this
.
value
===
FileType
.
Image
return
this
.
value
===
FileType
.
Image
;
}
private
get
others
()
{
return
this
.
value
===
FileType
.
Others
return
this
.
value
===
FileType
.
Others
;
}
private
get
pdf
()
{
return
this
.
value
===
FileType
.
Pdf
return
this
.
value
===
FileType
.
Pdf
;
}
private
get
ppt
()
{
return
this
.
value
===
FileType
.
Ppt
return
this
.
value
===
FileType
.
Ppt
;
}
private
get
rp
()
{
return
this
.
value
===
FileType
.
Rp
return
this
.
value
===
FileType
.
Rp
;
}
private
get
txt
()
{
return
this
.
value
===
FileType
.
Txt
return
this
.
value
===
FileType
.
Txt
;
}
private
get
video
()
{
return
this
.
value
===
FileType
.
Video
return
this
.
value
===
FileType
.
Video
;
}
private
get
word
()
{
return
this
.
value
===
FileType
.
Word
return
this
.
value
===
FileType
.
Word
;
}
private
get
xmid
()
{
return
this
.
value
===
FileType
.
Xmind
return
this
.
value
===
FileType
.
Xmind
;
}
private
get
zip
()
{
return
this
.
value
===
FileType
.
Zip
return
this
.
value
===
FileType
.
Zip
;
}
private
get
html
()
{
return
getSvg
(
this
.
value
)
return
getSvg
(
this
.
value
)
;
}
}
</
script
>
...
...
components/image-preview.vue
View file @
03c9c8d6
...
...
@@ -31,7 +31,7 @@
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
,
Model
,
Prop
}
from
"vue-property-decorator"
import
{
Component
,
Model
,
Prop
,
Vue
}
from
"vue-property-decorator"
;
@
Component
({
components
:
{}
})
export
default
class
ImagePreview
extends
Vue
{
...
...
@@ -42,8 +42,8 @@ export default class ImagePreview extends Vue {
private
file
!
:
{
name
:
string
;
url
:
string
}
private
style
:
{
"max-height"
:
number
|
string
"max-width"
:
number
|
string
"max-height"
:
number
|
string
;
"max-width"
:
number
|
string
;
}
=
{
"max-height"
:
"300px"
,
"max-width"
:
"600px"
,
...
...
@@ -54,19 +54,19 @@ export default class ImagePreview extends Vue {
()
=>
(
this
.
style
=
{
"max-height"
:
"300px"
,
"max-width"
:
"600px"
}),
300
)
this
.
$emit
(
"update"
,
false
)
)
;
this
.
$emit
(
"update"
,
false
)
;
}
private
set2Default
()
{
this
.
style
=
{
"max-height"
:
"1600px"
,
"max-width"
:
"1600px"
}
this
.
style
=
{
"max-height"
:
"1600px"
,
"max-width"
:
"1600px"
}
;
}
private
get
getAttachment
()
{
if
(
this
.
file
)
{
return
this
.
file
.
name
return
this
.
file
.
name
;
}
return
"文件下载"
return
"文件下载"
;
}
}
</
script
>
...
...
components/message.vue
View file @
03c9c8d6
...
...
@@ -142,25 +142,28 @@
</template>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
,
Prop
,
Ref
,
Inject
}
from
"vue-property-decorator"
import
*
as
dto
from
"../model"
import
chat
from
"./../xim"
import
{
chatStore
,
ChatStore
}
from
"@/customer-service/store/model"
import
FileIcon
from
"./file-icon.vue"
import
{
Component
,
Inject
,
Prop
,
Ref
,
Vue
}
from
"vue-property-decorator"
;
import
*
as
dto
from
"../model"
;
import
{
isAccessibleUrl
}
from
"../service/tools"
;
import
{
replaceText2Link
}
from
"../utils"
;
import
chat
from
"./../xim"
;
import
{
FileType
,
getFileType
,
isAudio
,
isImage
,
isVideo
,
MAX_FILE_SIZE
,
MAX_IMAGE_SIZE
,
isImage
,
}
from
"./file-controller"
import
V
oiceIcon
from
"./voice.vue"
import
WhoReadList
from
"./who-read-list.vue"
import
VideoPlayerIcon
from
"./video-player-icon.vue"
import
{
replaceText2Link
}
from
"../utils"
import
{
isAccessibleUrl
}
from
"../service/tools"
}
from
"./file-controller"
;
import
FileIcon
from
"./file-icon.vue"
;
import
V
ideoPlayerIcon
from
"./video-player-icon.vue"
;
import
VoiceIcon
from
"./voice.vue"
;
import
WhoReadList
from
"./who-read-list.vue"
;
import
{
chatStore
,
ChatStore
}
from
"@/customer-service/store/model"
;
@
Component
({
components
:
{
FileIcon
,
VoiceIcon
,
WhoReadList
,
VideoPlayerIcon
},
...
...
@@ -168,6 +171,7 @@ import { isAccessibleUrl } from "../service/tools"
export
default
class
Message
extends
Vue
{
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_MY_ID
)
private
readonly
chatMyId
!
:
ChatStore
.
STATE_CHAT_MY_ID
@
chatStore
.
Getter
(
ChatStore
.
GETTER_CURRENT_CHAT_PRESENT_MEMBERS
)
private
readonly
chatMembers
!
:
ChatStore
.
GETTER_CURRENT_CHAT_PRESENT_MEMBERS
...
...
@@ -211,127 +215,127 @@ export default class Message extends Vue {
private
org
=
""
private
get
isAllRead
()
{
return
this
.
data
.
read_count
>=
this
.
data
.
total_read_count
return
this
.
data
.
read_count
>=
this
.
data
.
total_read_count
;
}
private
get
messageBody
():
{
eid
?:
string
;
oid
?:
string
;
msg
:
any
}
{
if
(
this
.
data
)
{
try
{
return
{
...
this
.
data
,
msg
:
JSON
.
parse
(
this
.
data
.
msg
)
}
return
{
...
this
.
data
,
msg
:
JSON
.
parse
(
this
.
data
.
msg
)
}
;
}
catch
{
return
{
...
this
.
data
,
msg
:
JSON
.
parse
(
this
.
data
.
msg
.
replace
(
/
\n
/g
,
"\\n"
)),
}
}
;
}
}
return
{
msg
:
{
text
:
""
}
}
return
{
msg
:
{
text
:
""
}
}
;
}
private
get
getAttachment
()
{
if
(
this
.
messageBody
)
{
return
this
.
messageBody
.
msg
.
name
return
this
.
messageBody
.
msg
.
name
;
}
return
"文件下载"
return
"文件下载"
;
}
private
get
isMyMessage
()
{
if
(
this
.
isSendingMessage
)
{
return
true
return
true
;
}
if
(
this
.
messageBody
)
{
const
msg
=
this
.
messageBody
const
msg
=
this
.
messageBody
;
if
(
this
.
chatSource
)
{
const
source
=
msg
.
msg
.
source
const
source
=
msg
.
msg
.
source
;
if
(
source
)
{
return
(
source
===
this
.
chatSource
&&
this
.
messageBody
.
eid
===
this
.
chatMyId
)
)
;
}
if
(
this
.
org
&&
this
.
messageBody
.
oid
)
{
return
(
this
.
messageBody
.
oid
===
this
.
org
&&
this
.
messageBody
.
eid
===
this
.
chatMyId
)
)
;
}
return
false
return
false
;
}
return
this
.
messageBody
.
eid
===
this
.
chatMyId
return
this
.
messageBody
.
eid
===
this
.
chatMyId
;
}
return
false
return
false
;
}
private
get
username
()
{
const
avatar
=
chat
.
getUserMapping
()
if
(
this
.
data
==
null
)
return
""
if
(
avatar
==
null
)
return
this
.
data
.
id
const
value
=
avatar
[
this
.
data
.
eid
]
if
(
value
==
null
)
return
""
if
(
value
.
name
==
null
)
return
""
return
value
.
name
const
avatar
=
chat
.
getUserMapping
()
;
if
(
this
.
data
==
null
)
return
""
;
if
(
avatar
==
null
)
return
this
.
data
.
id
;
const
value
=
avatar
[
this
.
data
.
eid
]
;
if
(
value
==
null
)
return
""
;
if
(
value
.
name
==
null
)
return
""
;
return
value
.
name
;
}
private
get
avatar
()
{
const
avatar
=
chat
.
getUserMapping
()
const
avatar
=
chat
.
getUserMapping
()
;
if
(
this
.
isSendingMessage
)
{
if
(
avatar
&&
this
.
chatMyId
)
{
const
user
=
avatar
[
this
.
chatMyId
]
const
user
=
avatar
[
this
.
chatMyId
]
;
if
(
user
&&
user
.
avatar
)
{
return
user
.
avatar
return
user
.
avatar
;
}
}
}
if
(
avatar
&&
this
.
data
)
{
const
value
=
avatar
[
this
.
data
.
eid
]
const
value
=
avatar
[
this
.
data
.
eid
]
;
if
(
value
&&
value
.
avatar
)
{
return
value
.
avatar
return
value
.
avatar
;
}
}
return
""
return
""
;
}
private
get
fileIcon
()
{
if
(
this
.
data
)
{
return
getFileType
(
this
.
messageBody
.
msg
.
name
)
return
getFileType
(
this
.
messageBody
.
msg
.
name
)
;
}
return
FileType
.
Others
return
FileType
.
Others
;
}
private
get
messageType
()
{
const
type
=
this
.
data
?.
type
const
type
=
this
.
data
?.
type
;
if
(
type
===
"file"
)
{
const
name
=
this
.
messageBody
?.
msg
.
name
const
name
=
this
.
messageBody
?.
msg
.
name
;
if
(
name
)
{
const
size
=
this
.
messageBody
?.
msg
.
size
const
size
=
this
.
messageBody
?.
msg
.
size
;
if
(
size
)
{
const
outImageSize
=
size
>
MAX_IMAGE_SIZE
const
outImageSize
=
size
>
MAX_IMAGE_SIZE
;
if
(
!
outImageSize
&&
isImage
(
name
))
{
return
"image"
return
"image"
;
}
const
outSize
=
size
>
MAX_FILE_SIZE
const
outSize
=
size
>
MAX_FILE_SIZE
;
if
(
!
outSize
)
{
if
(
isAudio
(
name
))
{
return
"voice"
return
"voice"
;
}
if
(
isVideo
(
name
))
{
return
"video"
return
"video"
;
}
}
}
}
}
return
this
.
data
?.
type
return
this
.
data
?.
type
;
}
// 图片的样式设置,通过js偶尔会有高度计算不准确, 直接通过css的处理目前看可以达到对应效果
...
...
@@ -347,45 +351,45 @@ export default class Message extends Vue {
// }
private
get
duration
()
{
const
v
=
this
.
messageBody
.
msg
.
duration
as
number
return
v
||
0
const
v
=
this
.
messageBody
.
msg
.
duration
as
number
;
return
v
||
0
;
}
private
get
durationInSecond
()
{
return
Math
.
round
(
this
.
duration
/
1000
)
return
Math
.
round
(
this
.
duration
/
1000
)
;
}
private
get
getVoiceMessageWidth
()
{
if
(
this
.
fileFailed2Load
)
{
return
35
return
35
;
}
const
d
=
this
.
duration
/
1000
const
d
=
this
.
duration
/
1000
;
if
(
d
<=
3
)
{
return
60
return
60
;
}
if
(
d
>=
60
)
{
return
200
return
200
;
}
return
60
+
d
return
60
+
d
;
}
private
isCustomer
()
{
return
!
this
.
showReadSummary
return
!
this
.
showReadSummary
;
}
private
buildMessageUrl
()
{
if
(
this
.
messageRealUrl
||
this
.
loadingRealUrl
)
{
return
return
;
}
const
url
=
this
.
messageBody
.
msg
.
url
as
string
const
url
=
this
.
messageBody
.
msg
.
url
as
string
;
if
(
url
)
{
// const service = XimService.getInstance()
if
(
isAccessibleUrl
(
url
))
{
return
(
this
.
messageRealUrl
=
url
)
return
(
this
.
messageRealUrl
=
url
)
;
}
this
.
loadingRealUrl
=
true
this
.
loadingRealUrl
=
true
;
// service
// .getFileUrlById(url, this.chatId || 0, this.isCustomer())
// .then((data) => {
...
...
@@ -398,43 +402,43 @@ export default class Message extends Vue {
// .catch(() => (this.fileFailed2Load = true))
// .finally(() => (this.loadingRealUrl = false))
}
else
{
this
.
fileFailed2Load
=
true
this
.
fileFailed2Load
=
true
;
}
}
private
openFile
()
{
if
(
this
.
isSendingMessage
)
{
return
return
;
}
if
(
this
.
failed
||
this
.
fileFailed2Load
)
{
return
return
;
}
const
copy
=
{
...
this
.
messageBody
.
msg
}
const
copy
=
{
...
this
.
messageBody
.
msg
}
;
if
(
this
.
messageRealUrl
)
{
copy
.
url
=
this
.
messageRealUrl
copy
.
url
=
this
.
messageRealUrl
;
}
this
.
$emit
(
"open"
,
{
type
:
this
.
messageType
,
msg
:
copy
})
this
.
$emit
(
"open"
,
{
type
:
this
.
messageType
,
msg
:
copy
})
;
}
private
play
()
{
if
(
this
.
audioRef
?.
paused
)
{
this
.
audioRef
?.
load
()
this
.
audioRef
?.
play
()
this
.
audioRef
?.
load
()
;
this
.
audioRef
?.
play
()
;
}
else
{
this
.
audioRef
?.
pause
()
this
.
audioRef
?.
pause
()
;
}
}
private
onPlay
()
{
this
.
playing
=
true
this
.
playing
=
true
;
}
private
onPause
()
{
this
.
playing
=
false
this
.
playing
=
false
;
}
private
format2Link
(
text
:
string
)
{
return
replaceText2Link
(
text
)
return
replaceText2Link
(
text
)
;
}
}
</
script
>
...
...
components/video-player-icon.vue
View file @
03c9c8d6
...
...
@@ -30,7 +30,7 @@
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
}
from
"vue-property-decorator"
import
{
Component
,
Vue
}
from
"vue-property-decorator"
;
@
Component
({
components
:
{}
})
export
default
class
VideoPlayerIcon
extends
Vue
{}
...
...
components/video-preview.vue
View file @
03c9c8d6
...
...
@@ -37,7 +37,7 @@
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
,
Model
,
Prop
,
Ref
,
Watch
}
from
"vue-property-decorator"
import
{
Component
,
Model
,
Prop
,
Ref
,
Vue
,
Watch
}
from
"vue-property-decorator"
;
@
Component
({
components
:
{}
})
export
default
class
VideoPreview
extends
Vue
{
...
...
@@ -51,8 +51,8 @@ export default class VideoPreview extends Vue {
private
video
!
:
HTMLVideoElement
private
style
:
{
"max-height"
:
number
|
string
"max-width"
:
number
|
string
"max-height"
:
number
|
string
;
"max-width"
:
number
|
string
;
}
=
{
"max-height"
:
"800px"
,
"max-width"
:
"800px"
,
...
...
@@ -63,28 +63,28 @@ export default class VideoPreview extends Vue {
()
=>
(
this
.
style
=
{
"max-height"
:
"300px"
,
"max-width"
:
"600px"
}),
300
)
this
.
$emit
(
"update"
,
false
)
)
;
this
.
$emit
(
"update"
,
false
)
;
}
private
set2Default
()
{
this
.
style
=
{
"max-height"
:
"1600px"
,
"max-width"
:
"1600px"
}
this
.
style
=
{
"max-height"
:
"1600px"
,
"max-width"
:
"1600px"
}
;
}
private
get
getAttachment
()
{
if
(
this
.
file
)
{
return
this
.
file
.
name
return
this
.
file
.
name
;
}
return
"视频下载"
return
"视频下载"
;
}
@
Watch
(
"value"
)
private
onOpen
()
{
if
(
this
.
value
)
{
this
.
video
?.
load
()
setTimeout
(()
=>
this
.
video
?.
play
(),
100
)
this
.
video
?.
load
()
;
setTimeout
(()
=>
this
.
video
?.
play
(),
100
)
;
}
else
{
this
.
video
?.
pause
()
this
.
video
?.
pause
()
;
}
}
}
...
...
components/voice.vue
View file @
03c9c8d6
...
...
@@ -32,9 +32,9 @@
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
}
from
"vue-property-decorator"
import
{
Prop
}
from
"vue-property-decorator"
import
{
Watch
}
from
"vue-property-decorator"
import
{
Component
,
Prop
,
Vue
,
Watch
}
from
"vue-property-decorator"
;
@
Component
({
components
:
{}
})
export
default
class
VoiceIcon
extends
Vue
{
...
...
@@ -51,21 +51,21 @@ export default class VoiceIcon extends Vue {
private
onLoadingChanged
()
{
if
(
this
.
loading
)
{
this
.
interval
=
window
.
setInterval
(()
=>
{
const
v
=
this
.
status
+
1
const
v
=
this
.
status
+
1
;
if
(
v
>
3
)
{
this
.
status
=
0
this
.
status
=
0
;
}
else
{
this
.
status
=
v
this
.
status
=
v
;
}
},
500
)
},
500
)
;
}
else
{
clearInterval
(
this
.
interval
)
this
.
status
=
0
clearInterval
(
this
.
interval
)
;
this
.
status
=
0
;
}
}
beforeDestroy
()
{
clearInterval
(
this
.
interval
)
clearInterval
(
this
.
interval
)
;
}
}
</
script
>
components/who-read-list.vue
View file @
03c9c8d6
...
...
@@ -41,19 +41,21 @@
</div>
</template>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
,
Prop
,
Ref
}
from
"vue-property-decorator"
import
{
namespace
}
from
"vuex-class"
import
{
ChatStore
}
from
"@/customer-service/store/model"
import
xim
from
"@/customer-service/xim/xim"
import
{
unique
}
from
"../utils"
import
chat
from
"../xim"
import
*
as
dto
from
"../model"
import
{
Component
,
Prop
,
Ref
,
Vue
}
from
"vue-property-decorator"
;
import
{
namespace
}
from
"vuex-class"
;
const
chatStoreNamespace
=
namespace
(
"chatStore"
)
import
*
as
dto
from
"../model"
;
import
{
unique
}
from
"../utils"
;
import
{
ChatStore
}
from
"@/customer-service/store/model"
;
import
xim
from
"@/customer-service/xim/xim"
;
const
chatStoreNamespace
=
namespace
(
"chatStore"
);
@
Component
({
components
:
{}
})
export
default
class
WhoReadList
extends
Vue
{
@
chatStoreNamespace
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
)
private
readonly
chatId
!
:
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
@
chatStoreNamespace
.
State
(
ChatStore
.
STATE_CHAT_MY_ID
)
private
readonly
chatMyId
!
:
ChatStore
.
STATE_CHAT_MY_ID
...
...
@@ -61,6 +63,7 @@ export default class WhoReadList extends Vue {
type
:
Number
,
})
private
msgId
!
:
number
@
Ref
(
"list-con"
)
private
listCon
!
:
HTMLElement
...
...
@@ -70,74 +73,79 @@ export default class WhoReadList extends Vue {
private
unreadlist
:
{
name
:
string
;
avatar
:
string
}[]
=
[]
private
loading
=
false
private
startLoading
()
{
this
.
loading
=
true
this
.
loading
=
true
;
}
private
endLoading
()
{
this
.
loading
=
false
this
.
loading
=
false
;
}
public
async
created
()
{
this
.
startLoading
()
await
this
.
getReader
()
this
.
endLoading
()
this
.
startLoading
()
;
await
this
.
getReader
()
;
this
.
endLoading
()
;
}
public
mounted
()
{
this
.
enableBlur
()
this
.
enableBlur
()
;
const
{
top
,
left
}
=
(
this
.
listCon
.
parentNode
as
HTMLElement
).
getBoundingClientRect
()
this
.
top
=
top
this
.
left
=
left
).
getBoundingClientRect
()
;
this
.
top
=
top
;
this
.
left
=
left
;
}
private
enableBlur
()
{
this
.
listCon
.
setAttribute
(
"tabindex"
,
"-1"
)
this
.
listCon
.
focus
()
this
.
listCon
.
setAttribute
(
"tabindex"
,
"-1"
)
;
this
.
listCon
.
focus
()
;
}
private
async
getUserNameByid
(
eid
:
string
)
{
const
data
=
await
this
.
sdk
.
model
(
"user"
).
detail
(
eid
).
query
()
return
data
.
row
.
first_name
.
value
as
string
const
data
=
await
this
.
sdk
.
model
(
"user"
).
detail
(
eid
).
query
()
;
return
data
.
row
.
first_name
.
value
as
string
;
}
private
async
getReader
()
{
if
(
this
.
chatId
==
null
)
return
if
(
this
.
msgId
==
null
)
return
const
userInfo
=
chat
.
getUserMapping
()
const
data
=
await
xim
.
fetchMsgInBox
(
this
.
chatId
,
this
.
msgId
)
if
(
this
.
chatId
==
null
)
return
;
if
(
this
.
msgId
==
null
)
return
;
const
data
=
await
xim
.
fetchMsgInBox
(
this
.
chatId
,
this
.
msgId
);
const
readerlist
=
this
.
uniqueReaderList
(
data
.
args
[
0
]
as
dto
.
OneWhoReadMessage
[]
)
)
;
this
.
readlist
=
await
Promise
.
all
(
readerlist
.
filter
((
k
)
=>
k
.
is_read
)
.
filter
((
k
)
=>
k
.
eid
!==
this
.
chatMyId
)
.
map
(
async
(
k
)
=>
{
const
eid
=
k
.
eid
const
name
=
await
this
.
getUserNameByid
(
eid
)
const
eid
=
k
.
eid
;
const
name
=
await
this
.
getUserNameByid
(
eid
)
;
return
{
eid
,
name
,
avatar
:
""
,
}
}
;
})
)
)
;
this
.
unreadlist
=
await
Promise
.
all
(
readerlist
.
filter
((
k
)
=>
!
k
.
is_read
)
.
filter
((
k
)
=>
k
.
eid
!==
this
.
chatMyId
)
.
map
(
async
(
k
)
=>
{
const
eid
=
k
.
eid
const
name
=
await
this
.
getUserNameByid
(
eid
)
const
eid
=
k
.
eid
;
const
name
=
await
this
.
getUserNameByid
(
eid
)
;
return
{
eid
,
name
,
avatar
:
""
,
}
}
;
})
)
)
;
}
private
uniqueReaderList
(
data
:
dto
.
OneWhoReadMessage
[])
{
return
unique
(
data
,
function
(
item
,
all
)
{
return
all
.
findIndex
((
k
)
=>
k
.
eid
===
item
.
eid
)
})
return
all
.
findIndex
((
k
)
=>
k
.
eid
===
item
.
eid
)
;
})
;
}
}
</
script
>
...
...
hybrid-input/index.vue
View file @
03c9c8d6
...
...
@@ -237,7 +237,7 @@ export default class Input extends Vue {
}
}
else
{
promiseArr
.
push
(
new
Promise
<
void
>
((
res
lo
ve
)
=>
{
new
Promise
<
void
>
((
res
ol
ve
)
=>
{
const
contentType
=
items
[
i
].
type
;
items
[
i
].
getAsString
((
k
)
=>
{
/*
...
...
@@ -267,7 +267,7 @@ export default class Input extends Vue {
}
}
while
(
result
);
}
res
lo
ve
();
res
ol
ve
();
});
})
);
...
...
@@ -514,10 +514,6 @@ export default class Input extends Vue {
this
.
emojiPanelVisibility
=
false
;
}
private
noop
()
{
}
private
setupEmoji
()
{
EmojiService
.
onReady
(()
=>
{
const
service
=
new
EmojiService
();
...
...
message-input.vue
View file @
03c9c8d6
...
...
@@ -9,23 +9,26 @@
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
Component
,
Ref
,
Vue
,
Watch
}
from
"vue-property-decorator"
import
{
Component
,
Ref
,
Vue
,
Watch
}
from
"vue-property-decorator"
;
import
ChatInput
,
{
FILE_INFO_CLASS
,
isImageOrFile
,
}
from
"./hybrid-input/index.vue"
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
import
{
ChatLoggerService
}
from
"./xim/logger"
import
xim
from
"./xim/xim"
import
{
Message
}
from
"./model"
import
{
uploadFile
}
from
"./service/upload"
}
from
"./hybrid-input/index.vue"
;
import
{
Message
}
from
"./model"
;
import
{
uploadFile
}
from
"./service/upload"
;
import
{
ChatLoggerService
}
from
"./xim/logger"
;
import
xim
from
"./xim/xim"
;
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
;
let
sendingMessageIndex
=
1
let
sendingMessageIndex
=
1
;
@
Component
({
components
:
{
ChatInput
}
})
export
default
class
MessageInput
extends
Vue
{
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_DIALOG_VISIBLE
)
private
readonly
chatRoomVisible
:
ChatStore
.
STATE_CHAT_DIALOG_VISIBLE
@
chatStore
.
Action
(
ChatStore
.
ACTION_SEND_MESSAGE
)
private
readonly
sendMsg
!
:
ChatStore
.
ACTION_SEND_MESSAGE
...
...
@@ -55,44 +58,45 @@ export default class MessageInput extends Vue {
@
Watch
(
"chatRoomVisible"
)
private
whenChatRoomShow
()
{
if
(
!
this
.
chatRoomVisible
)
return
this
.
chatInput
.
focus
()
if
(
!
this
.
chatRoomVisible
)
return
;
this
.
chatInput
.
focus
()
;
}
private
async
sendMessage
(
msg
:
ChildNode
[],
done
:
()
=>
void
)
{
if
(
this
.
chatIniting
)
{
return
return
;
}
for
(
const
item
of
msg
)
{
if
(
isImageOrFile
(
item
))
{
if
((
item
as
Element
).
classList
.
contains
(
FILE_INFO_CLASS
))
{
this
.
sendFile
(
item
,
"file"
)
this
.
sendFile
(
item
,
"file"
)
;
}
else
{
this
.
sendFile
(
item
,
"image"
)
this
.
sendFile
(
item
,
"image"
)
;
}
continue
continue
;
}
if
(
item
.
textContent
)
{
this
.
sendText
(
item
.
textContent
)
this
.
sendText
(
item
.
textContent
)
;
}
}
ChatLoggerService
.
logger
?.
debug
(
"all messages sent"
)
done
()
this
.
$emit
(
"sent"
)
ChatLoggerService
.
logger
?.
debug
(
"all messages sent"
)
;
done
()
;
this
.
$emit
(
"sent"
)
;
}
private
async
onInput
()
{
if
(
this
.
chatId
==
null
)
return
await
xim
.
inputing
(
this
.
chatId
)
if
(
this
.
chatId
==
null
)
return
;
await
xim
.
inputing
(
this
.
chatId
)
;
}
private
sendText
(
text
:
string
)
{
if
(
text
&&
text
.
trim
())
{
const
msg
=
{
text
:
text
.
trim
()
}
const
msg
=
{
text
:
text
.
trim
()
}
;
if
(
this
.
source
)
{
Object
.
assign
(
msg
,
{
source
:
this
.
source
})
Object
.
assign
(
msg
,
{
source
:
this
.
source
})
;
}
this
.
sendMsg
({
msgType
:
"text"
,
msg
:
JSON
.
stringify
(
msg
)
})
this
.
sendMsg
({
msgType
:
"text"
,
msg
:
JSON
.
stringify
(
msg
)
})
;
}
}
...
...
@@ -100,24 +104,24 @@ export default class MessageInput extends Vue {
const
src
=
JSON
.
parse
(
file
.
attributes
[
`data-
${
type
}
`
]?.
value
||
""
)
as
{
url
:
string
name
:
string
size
:
number
}
url
:
string
;
name
:
string
;
size
:
number
;
}
;
if
(
src
)
{
const
index
=
this
.
sendSendingMessage
(
type
,
src
)
const
file
=
await
this
.
readBlobUrl2Base64
(
src
.
url
,
src
.
name
)
const
index
=
this
.
sendSendingMessage
(
type
,
src
)
;
const
file
=
await
this
.
readBlobUrl2Base64
(
src
.
url
,
src
.
name
)
;
if
(
file
)
{
let
w
=
0
let
h
=
0
let
w
=
0
;
let
h
=
0
;
if
(
type
===
"image"
)
{
const
img
=
new
Image
()
img
.
src
=
src
.
url
const
img
=
new
Image
()
;
img
.
src
=
src
.
url
;
img
.
onload
=
function
()
{
w
=
img
.
naturalWidth
h
=
img
.
naturalHeight
}
img
.
remove
()
w
=
img
.
naturalWidth
;
h
=
img
.
naturalHeight
;
}
;
img
.
remove
()
;
}
uploadFile
(
file
,
this
.
chatId
||
0
,
w
,
h
)
.
then
((
r
)
=>
{
...
...
@@ -126,42 +130,43 @@ export default class MessageInput extends Vue {
url
:
r
,
name
:
file
.
name
,
size
:
file
.
size
,
}
}
;
if
(
this
.
source
)
{
Object
.
assign
(
msg
,
{
source
:
this
.
source
})
Object
.
assign
(
msg
,
{
source
:
this
.
source
})
;
}
if
(
w
&&
h
)
{
Object
.
assign
(
msg
,
{
w
,
h
})
Object
.
assign
(
msg
,
{
w
,
h
})
;
}
this
.
sendMsg
({
msgType
:
type
,
msg
:
JSON
.
stringify
(
msg
),
})
this
.
removeSendingMessages
(
index
)
URL
.
revokeObjectURL
(
src
.
url
)
})
;
this
.
removeSendingMessages
(
index
)
;
URL
.
revokeObjectURL
(
src
.
url
)
;
}
else
{
this
.
setMsg2Failed
(
index
)
this
.
setMsg2Failed
(
index
)
;
}
})
.
catch
((
e
)
=>
{
console
.
error
(
e
)
// eslint-disable-next-line no-console
console
.
error
(
e
);
this
.
setMsg2Failed
(
index
)
})
this
.
setMsg2Failed
(
index
)
;
})
;
}
}
}
private
setMsg2Failed
(
index
:
number
)
{
this
.
failedSendingMessage
(
index
)
this
.
failedSendingMessage
(
index
)
;
}
private
sendSendingMessage
(
type
:
string
,
msg
:
any
)
{
const
index
=
sendingMessageIndex
++
const
index
=
sendingMessageIndex
++
;
if
(
this
.
source
)
{
Object
.
assign
(
msg
,
{
source
:
this
.
source
,
eid
:
this
.
chatMyId
})
Object
.
assign
(
msg
,
{
source
:
this
.
source
,
eid
:
this
.
chatMyId
})
;
}
if
(
this
.
chatId
)
{
this
.
appendSendingMessages
({
...
...
@@ -170,20 +175,20 @@ export default class MessageInput extends Vue {
ts
:
Date
.
now
(),
type
,
msg
:
JSON
.
stringify
(
msg
),
}
as
Message
)
return
-
index
}
as
Message
)
;
return
-
index
;
}
return
0
return
0
;
}
private
readBlobUrl2Base64
(
url
:
string
,
name
:
string
)
{
return
fetch
(
url
)
.
then
((
r
)
=>
r
.
blob
())
.
then
((
blob
)
=>
new
File
([
blob
],
name
))
.
then
((
blob
)
=>
new
File
([
blob
],
name
))
;
}
private
onError
(
e
:
any
)
{
this
.
$emit
(
"error"
,
e
.
message
||
e
)
this
.
$emit
(
"error"
,
e
.
message
||
e
)
;
}
}
</
script
>
message-list.vue
View file @
03c9c8d6
...
...
@@ -43,14 +43,16 @@
</template>
<
script
lang=
"ts"
>
import
{
Component
,
Vue
,
Ref
,
Prop
,
Watch
}
from
"vue-property-decorator"
import
message
from
"./components/message.vue"
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
import
{
throttle
}
from
"./utils"
import
{
formatTime
}
from
"./utils/time"
import
{
Message
}
from
"./model"
import
ImagePreview
from
"./components/image-preview.vue"
import
VideoPreview
from
"./components/video-preview.vue"
import
{
Component
,
Prop
,
Ref
,
Vue
,
Watch
}
from
"vue-property-decorator"
;
import
ImagePreview
from
"./components/image-preview.vue"
;
import
message
from
"./components/message.vue"
;
import
VideoPreview
from
"./components/video-preview.vue"
;
import
{
Message
}
from
"./model"
;
import
{
throttle
}
from
"./utils"
;
import
{
formatTime
}
from
"./utils/time"
;
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
;
@
Component
({
components
:
{
message
,
ImagePreview
,
VideoPreview
}
})
export
default
class
MessageList
extends
Vue
{
...
...
@@ -89,16 +91,16 @@ export default class MessageList extends Vue {
if
(
this
.
sendingMessages
)
{
return
[...
this
.
historyMessage
,
...
this
.
sendingMessages
].
filter
(
(
i
)
=>
i
.
chat_id
===
this
.
chatId
)
)
;
}
return
this
.
historyMessage
return
this
.
historyMessage
;
}
if
(
this
.
sendingMessages
)
{
return
this
.
sendingMessages
.
filter
((
i
)
=>
i
.
chat_id
===
this
.
chatId
)
return
this
.
sendingMessages
.
filter
((
i
)
=>
i
.
chat_id
===
this
.
chatId
)
;
}
return
[]
return
[]
;
}
// 添加时间戳的最大间隔消息数
...
...
@@ -114,37 +116,39 @@ export default class MessageList extends Vue {
@
Ref
(
"message-scrollbar"
)
private
scollbarElement
!
:
Vue
&
{
update
:
()
=>
void
update
:
()
=>
void
;
}
private
get
scollWrapper
():
HTMLElement
|
null
{
return
this
.
scollbarElement
?.
$el
?.
firstChild
as
HTMLElement
return
this
.
scollbarElement
?.
$el
?.
firstChild
as
HTMLElement
;
}
@
Watch
(
"messages"
)
private
whenHasMessages
()
{
this
.
$nextTick
(()
=>
this
.
scollbarElement
.
update
())
this
.
$nextTick
(()
=>
this
.
scollbarElement
.
update
())
;
}
@
Watch
(
"preview"
)
private
onPreviewChanged
()
{
if
(
!
this
.
preview
)
{
this
.
raiseFileOpen
(
false
)
this
.
raiseFileOpen
(
false
)
;
}
}
@
Watch
(
"previewVideo"
)
private
onVideoPreviewChanged
()
{
if
(
!
this
.
previewVideo
)
{
this
.
raiseFileOpen
(
false
)
this
.
raiseFileOpen
(
false
)
;
}
}
private
raiseFileOpen
(
value
:
boolean
)
{
this
.
$emit
(
"file-open"
,
value
)
this
.
$emit
(
"file-open"
,
value
)
;
}
private
get
messageTimestampDictionary
()
{
const
dic
=
{}
as
{
[
prop
:
number
]:
boolean
}
let
count
=
0
const
dic
=
{}
as
{
[
prop
:
number
]:
boolean
}
;
let
count
=
0
;
if
(
this
.
historyMessage
)
{
this
.
historyMessage
.
forEach
((
message
,
index
,
array
)
=>
{
...
...
@@ -153,15 +157,15 @@ export default class MessageList extends Vue {
this
.
whetherShowTime
(
array
[
index
-
1
],
message
)
||
count
===
this
.
timeLimit
-
1
)
{
dic
[
message
.
id
]
=
true
count
=
0
dic
[
message
.
id
]
=
true
;
count
=
0
;
}
else
{
count
++
count
++
;
}
})
})
;
}
return
dic
return
dic
;
}
private
loading
=
false
...
...
@@ -169,163 +173,167 @@ export default class MessageList extends Vue {
private
loadingNew
=
false
public
created
()
{
this
.
handleScrollWrapper
()
this
.
handleScrollWrapper
()
;
}
public
mounted
()
{
this
.
scollWrapper
&&
this
.
scollWrapper
.
addEventListener
(
"scroll"
,
this
.
handleScroll
)
this
.
saveScrollToBottomFunc
(
this
.
scrollToNewMsg
)
this
.
scollWrapper
.
addEventListener
(
"scroll"
,
this
.
handleScroll
)
;
this
.
saveScrollToBottomFunc
(
this
.
scrollToNewMsg
)
;
}
public
beforeDestroy
()
{
this
.
scollWrapper
&&
this
.
scollWrapper
.
removeEventListener
(
"scroll"
,
this
.
handleScroll
)
this
.
clearScrollToBottomFunc
()
this
.
clearChatId
()
this
.
scollWrapper
.
removeEventListener
(
"scroll"
,
this
.
handleScroll
)
;
this
.
clearScrollToBottomFunc
()
;
this
.
clearChatId
()
;
}
public
scroll2End
(
delay
?:
number
)
{
this
.
$nextTick
(()
=>
{
const
wrap
=
this
.
scollbarElement
?.
$el
.
querySelector
(
".el-scrollbar__wrap"
)
as
HTMLElement
)
as
HTMLElement
;
if
(
wrap
)
{
if
(
delay
)
{
setTimeout
(()
=>
{
wrap
.
scrollTop
=
10000
},
delay
)
return
wrap
.
scrollTop
=
10000
;
},
delay
)
;
return
;
}
wrap
.
scrollTop
=
10000
wrap
.
scrollTop
=
10000
;
}
})
})
;
}
private
startLoading
()
{
this
.
loading
=
true
this
.
loading
=
true
;
}
private
endLoading
()
{
this
.
loading
=
false
this
.
loading
=
false
;
}
private
startLoadingOld
()
{
this
.
startLoading
()
this
.
loadingOld
=
true
this
.
startLoading
()
;
this
.
loadingOld
=
true
;
}
private
endLoadingOld
()
{
this
.
endLoading
()
this
.
loadingOld
=
false
this
.
endLoading
()
;
this
.
loadingOld
=
false
;
}
private
startLoadingNew
()
{
this
.
startLoading
()
this
.
loadingNew
=
true
this
.
startLoading
()
;
this
.
loadingNew
=
true
;
}
private
endLoadingNew
()
{
this
.
endLoading
()
this
.
loadingNew
=
false
this
.
endLoading
()
;
this
.
loadingNew
=
false
;
}
private
handleScroll
!
:
()
=>
void
private
handleScrollWrapper
()
{
let
oldScrollTop
=
0
let
oldScrollTop
=
0
;
this
.
handleScroll
=
()
=>
{
const
wrapper
=
this
.
scollWrapper
const
gap
=
150
if
(
wrapper
==
null
)
return
const
view
=
wrapper
.
firstChild
as
HTMLElement
const
wrapperH
=
wrapper
.
getBoundingClientRect
().
height
const
viewH
=
view
.
getBoundingClientRect
().
height
let
scrollUp
=
false
let
scrollDown
=
false
const
wrapper
=
this
.
scollWrapper
;
const
gap
=
150
;
if
(
wrapper
==
null
)
return
;
const
view
=
wrapper
.
firstChild
as
HTMLElement
;
const
wrapperH
=
wrapper
.
getBoundingClientRect
().
height
;
const
viewH
=
view
.
getBoundingClientRect
().
height
;
let
scrollUp
=
false
;
let
scrollDown
=
false
;
if
(
oldScrollTop
>
wrapper
.
scrollTop
)
{
scrollUp
=
true
scrollDown
=
false
scrollUp
=
true
;
scrollDown
=
false
;
}
else
if
(
oldScrollTop
<
wrapper
.
scrollTop
)
{
scrollUp
=
false
scrollDown
=
true
scrollUp
=
false
;
scrollDown
=
true
;
}
this
.
forbidScrollTopToZero
(
wrapper
)
this
.
forbidScrollTopToZero
(
wrapper
)
;
if
(
wrapper
.
scrollTop
<=
gap
)
{
scrollUp
&&
this
.
fetchOldMsg
()
scrollUp
&&
this
.
fetchOldMsg
()
;
}
if
(
wrapper
.
scrollTop
-
40
-
(
viewH
-
wrapperH
)
>=
-
gap
)
{
scrollDown
&&
this
.
fetchNewMsg
()
}
oldScrollTop
=
wrapper
.
scrollTop
scrollDown
&&
this
.
fetchNewMsg
();
}
oldScrollTop
=
wrapper
.
scrollTop
;
};
}
/* scrollTop为0时,新加载的消息后,滚动条也会保持在0的位置 */
private
forbidScrollTopToZero
(
ele
:
HTMLElement
)
{
if
(
ele
.
scrollTop
<=
10
)
{
ele
.
scrollTop
=
10
ele
.
scrollTop
=
10
;
}
}
private
scrollToNewMsg
()
{
this
.
$nextTick
(()
=>
{
if
(
this
.
loading
)
return
this
.
scroll2End
()
})
if
(
this
.
loading
)
return
;
this
.
scroll2End
()
;
})
;
}
@
throttle
()
private
async
fetchOldMsg
()
{
if
(
this
.
loading
)
return
const
msg
=
this
.
historyMessage
if
(
msg
==
null
)
return
if
(
msg
.
length
===
0
)
return
this
.
startLoadingOld
()
const
msgId
=
msg
[
0
].
id
const
data
=
await
this
.
getLastPageMsg
(
msgId
)
if
(
this
.
loading
)
return
;
const
msg
=
this
.
historyMessage
;
if
(
msg
==
null
)
return
;
if
(
msg
.
length
===
0
)
return
;
this
.
startLoadingOld
()
;
const
msgId
=
msg
[
0
].
id
;
const
data
=
await
this
.
getLastPageMsg
(
msgId
)
;
if
(
data
.
length
===
0
)
{
console
.
log
(
"没有更多老消息了"
)
// eslint-disable-next-line no-console
console
.
log
(
"没有更多老消息了"
);
}
this
.
$emit
(
"last-page"
,
msgId
)
this
.
endLoadingOld
()
this
.
$emit
(
"last-page"
,
msgId
)
;
this
.
endLoadingOld
()
;
}
@
throttle
()
private
async
fetchNewMsg
()
{
if
(
this
.
loading
)
return
const
msg
=
this
.
historyMessage
if
(
msg
==
null
)
return
if
(
msg
.
length
===
0
)
return
this
.
startLoadingNew
()
const
msgId
=
msg
[
msg
.
length
-
1
].
id
const
data
=
await
this
.
getNextPageMsg
(
msgId
)
if
(
this
.
loading
)
return
;
const
msg
=
this
.
historyMessage
;
if
(
msg
==
null
)
return
;
if
(
msg
.
length
===
0
)
return
;
this
.
startLoadingNew
()
;
const
msgId
=
msg
[
msg
.
length
-
1
].
id
;
const
data
=
await
this
.
getNextPageMsg
(
msgId
)
;
if
(
data
.
length
===
0
)
{
console
.
log
(
"没有更多新消息了"
)
// eslint-disable-next-line no-console
console
.
log
(
"没有更多新消息了"
);
}
this
.
$emit
(
"next-page"
,
msgId
)
this
.
endLoadingNew
()
this
.
$emit
(
"next-page"
,
msgId
)
;
this
.
endLoadingNew
()
;
}
private
format2Time
(
time
:
number
)
{
return
formatTime
(
time
)
return
formatTime
(
time
)
;
}
private
whetherShowTime
(
previous
:
Message
,
current
:
Message
)
{
return
current
.
ts
-
previous
.
ts
>
180
return
current
.
ts
-
previous
.
ts
>
180
;
}
private
open
(
file
:
{
type
:
string
msg
:
{
url
:
string
;
name
:
string
;
size
:
number
}
type
:
string
;
msg
:
{
url
:
string
;
name
:
string
;
size
:
number
}
;
})
{
if
(
file
.
type
===
"image"
)
{
this
.
imagePreview
=
file
.
msg
this
.
preview
=
true
return
this
.
raiseFileOpen
(
true
)
this
.
imagePreview
=
file
.
msg
;
this
.
preview
=
true
;
return
this
.
raiseFileOpen
(
true
)
;
}
if
(
file
.
type
===
"video"
)
{
this
.
videoPreview
=
file
.
msg
this
.
previewVideo
=
true
return
this
.
raiseFileOpen
(
true
)
this
.
videoPreview
=
file
.
msg
;
this
.
previewVideo
=
true
;
return
this
.
raiseFileOpen
(
true
)
;
}
}
...
...
@@ -333,14 +341,14 @@ export default class MessageList extends Vue {
* 获取当期消息列表头尾消息的id
*/
public
getStart2EndMessageIds
()
{
const
v
:
{
start
:
number
;
end
:
number
}
=
{
start
:
0
,
end
:
0
}
const
v
:
{
start
:
number
;
end
:
number
}
=
{
start
:
0
,
end
:
0
}
;
if
(
this
.
historyMessage
&&
this
.
historyMessage
.
length
)
{
const
start
=
this
.
historyMessage
[
0
]
v
.
start
=
start
.
id
const
end
=
this
.
historyMessage
[
this
.
historyMessage
.
length
-
1
]
v
.
end
=
end
.
id
const
start
=
this
.
historyMessage
[
0
]
;
v
.
start
=
start
.
id
;
const
end
=
this
.
historyMessage
[
this
.
historyMessage
.
length
-
1
]
;
v
.
end
=
end
.
id
;
}
return
v
return
v
;
}
}
</
script
>
...
...
store/index.ts
View file @
03c9c8d6
import
{
RootStoreState
}
from
"@/store/model"
;
import
{
Module
}
from
"vuex"
;
import
{
ChatMember
}
from
"../model"
;
...
...
@@ -5,28 +6,25 @@ import { isAccessibleUrl } from "../service/tools";
import
{
unique
}
from
"../utils"
;
import
{
decode
}
from
"../utils/jwt"
;
import
Chat
from
"../xim"
;
import
chat
from
"../xim/"
;
import
chatType
from
"../xim/chat-type"
;
import
xim
,
{
ChatNotifyListener
}
from
"../xim/xim"
;
import
{
ChatMemberType
,
ChatStatus
,
ChatStore
,
ChatStoreState
}
from
"./model"
;
import
{
RootStoreState
}
from
"@/store/model"
;
export
const
ns
=
ChatStore
.
ns
;
const
sdk
=
c
hat
.
getSdk
;
const
sdk
=
C
hat
.
getSdk
;
const
UniplatChatModelName
=
"UniplatChat"
;
const
model
=
()
=>
sdk
().
model
(
UniplatChatModelName
);
const
orgId
=
c
hat
.
getOrgId
;
const
getMyinfo
=
(
function
()
{
let
data
;
return
async
()
=>
{
if
(
data
!=
null
)
return
data
;
data
=
sdk
().
getUserInfo
();
return
data
;
};
})();
const
orgId
=
C
hat
.
getOrgId
;
//
const getMyinfo = (function () {
//
let data;
//
return async () => {
//
if (data != null) return data;
//
data = sdk().getUserInfo();
//
return data;
//
};
//
})();
function
uniqueMessages
(
messages
:
NonNullable
<
ChatStore
.
STATE_CHAT_MSG_HISTORY
>
)
{
...
...
@@ -49,23 +47,23 @@ const removeRegisterChatEvents: (() => void)[] = [];
async
function
preCacheImgs
(
msgs
:
any
[])
{
await
Promise
.
all
(
msgs
.
map
((
k
)
=>
{
return
new
Promise
((
don
e
:
(
p
:
void
)
=>
void
)
=>
{
return
new
Promise
((
resolv
e
:
(
p
:
void
)
=>
void
)
=>
{
if
(
k
.
type
===
"image"
)
{
const
msg
=
JSON
.
parse
(
k
.
msg
);
const
url
=
msg
.
url
;
if
(
!
isAccessibleUrl
(
url
))
{
don
e
();
resolv
e
();
}
if
(
url
&&
isAccessibleUrl
(
url
))
{
const
preCache
=
new
Image
();
preCache
.
src
=
url
;
preCache
.
onload
=
()
=>
don
e
();
setTimeout
(
don
e
,
2000
);
preCache
.
onload
=
()
=>
resolv
e
();
setTimeout
(
resolv
e
,
2000
);
}
else
{
don
e
();
resolv
e
();
}
}
else
{
don
e
();
resolv
e
();
}
});
})
...
...
@@ -291,7 +289,7 @@ export default {
actions
:
{
async
[
ChatStore
.
ACTION_GET_MY_CHAT_LIST
](
{
commit
},
...
params
:
Parameters
<
ChatStore
.
ACTION_GET_MY_CHAT_LIST
>
//
...params: Parameters<ChatStore.ACTION_GET_MY_CHAT_LIST>
)
{
const
{
pageData
}
=
await
model
().
list
().
query
({
pageIndex
:
1
,
...
...
@@ -316,12 +314,12 @@ export default {
total
:
pageData
.
record_count
,
});
},
async
[
ChatStore
.
ACTION_JOIN_CHAT
](
{
commit
},
chatId
:
Parameters
<
ChatStore
.
ACTION_JOIN_CHAT
>
[
0
]
)
{
// return await XimService.getInstance().joinChat(chatId)
},
//
async [ChatStore.ACTION_JOIN_CHAT](
//
{ commit },
//
chatId: Parameters<ChatStore.ACTION_JOIN_CHAT>[0]
//
) {
//
// return await XimService.getInstance().joinChat(chatId)
//
},
async
[
ChatStore
.
ACTION_GET_CHAT_MESSAGES
]({
state
,
commit
})
{
const
chatId
=
state
[
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
];
if
(
chatId
==
null
)
return
;
...
...
@@ -332,6 +330,7 @@ export default {
commit
(
ChatStore
.
MUTATION_SCROLL_TO_BOTTOM
);
return
data
;
}
catch
(
error
)
{
// eslint-disable-next-line no-console
console
.
error
(
error
);
}
},
...
...
@@ -379,6 +378,7 @@ export default {
await
dispatch
(
ChatStore
.
ACTION_GET_FRESH_MESSAGE
);
return
data
;
}
catch
(
error
)
{
// eslint-disable-next-line no-console
console
.
error
(
"testing 信息发送失败"
,
error
);
}
},
...
...
@@ -397,7 +397,7 @@ export default {
msgs
[
msgs
.
length
-
1
].
id
);
}
const
lastMsg
=
newMsgsArr
[
newMsgsArr
.
length
-
1
];
//
const lastMsg = newMsgsArr[newMsgsArr.length - 1];
await
preCacheImgs
(
newMsgsArr
);
commit
(
ChatStore
.
MUTATION_SCROLL_TO_BOTTOM
);
},
...
...
@@ -432,7 +432,7 @@ export default {
detailManager
.
done
();
const
{
id
}
=
await
action
.
dryExecute
();
// 无法得到chat id
const
data
=
await
sdk
()
await
sdk
()
.
model
(
UniplatChatModelName
)
.
action
(
"createXimChat"
)
.
updateInitialParams
({
...
...
@@ -451,13 +451,13 @@ export default {
uniplatId
:
newChat
.
uniplatId
,
});
},
async
[
ChatStore
.
ACTION_CREATE_NEW_CHAT_BY_CLIENT_SIDE
](
{
commit
,
dispatch
},
option
:
{
customerServiceId
?:
number
|
string
;
customerServiceGroupId
?:
number
;
}
)
{},
//
async [ChatStore.ACTION_CREATE_NEW_CHAT_BY_CLIENT_SIDE](
//
{ commit, dispatch },
//
option: {
//
customerServiceId?: number | string;
//
customerServiceGroupId?: number;
//
}
//
) {},
async
[
ChatStore
.
ACTION_REGISTER_EVENT
]({
dispatch
,
commit
,
state
})
{
const
chatId
=
state
[
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
];
if
(
chatId
==
null
)
return
;
...
...
@@ -471,7 +471,6 @@ export default {
)
{
return
;
}
console
.
log
(
"事件消息已读"
,
e
);
if
(
chatId
!==
e
.
chat_id
)
return
;
const
msgs
=
state
[
ChatStore
.
STATE_CHAT_MSG_HISTORY
];
if
(
msgs
==
null
)
return
;
...
...
@@ -554,6 +553,7 @@ export default {
phone
:
info
.
row
.
last_name
.
value
as
string
,
};
}
catch
(
error
)
{
// eslint-disable-next-line no-console
console
.
error
(
error
);
result
=
member
;
}
...
...
third-party/image/index.ts
View file @
03c9c8d6
...
...
@@ -25,14 +25,14 @@ export class ImageCompresser {
maxWidth
:
number
,
maxHeight
:
number
):
Promise
<
File
|
null
>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
return
new
Promise
<
File
>
((
resolve
,
reject
)
=>
{
const
img
=
new
Image
();
const
reader
=
new
FileReader
();
reader
.
onload
=
(
e
)
=>
{
if
(
e
&&
e
.
target
&&
e
.
target
.
result
)
{
img
.
src
=
e
.
target
.
result
as
string
;
}
else
{
reject
();
reject
(
new
Error
(
"file load failed"
)
);
}
};
reader
.
readAsDataURL
(
file
);
...
...
@@ -49,7 +49,7 @@ export class ImageCompresser {
newFile
.
size
<=
file
.
size
?
newFile
:
file
);
}
else
{
reject
();
reject
(
new
Error
(
"file load failed"
)
);
}
})
.
catch
(
reject
);
...
...
@@ -77,7 +77,7 @@ export class ImageCompresser {
const
canvas
=
document
.
createElement
(
"canvas"
);
const
context
=
canvas
.
getContext
(
"2d"
);
if
(
!
context
)
{
reject
();
reject
(
new
Error
(
" compress image failed"
)
);
return
;
}
const
{
width
:
originWidth
,
height
:
originHeight
}
=
img
;
// 最大尺寸限制
...
...
utils/jwt/index.ts
View file @
03c9c8d6
...
...
@@ -22,7 +22,7 @@ function base64_url_decode(str: string) {
output
+=
"="
;
break
;
default
:
throw
"Illegal base64url string!"
;
throw
new
Error
(
"Illegal base64url string!"
)
;
}
try
{
...
...
xim/index.ts
View file @
03c9c8d6
...
...
@@ -8,14 +8,14 @@ import tokenManager from "./token";
import
xim
from
"./xim"
;
class
Chat
{
private
_sdk
?:
()
=>
UniplatSdk
private
_orgId
:
()
=>
string
|
number
=
()
=>
"0"
private
token
!
:
TokenStringGetter
private
_sdk
?:
()
=>
UniplatSdk
;
private
_orgId
:
()
=>
string
|
number
=
()
=>
"0"
;
private
token
!
:
TokenStringGetter
;
private
userMapping
:
{
[
key
:
string
]:
{
name
:
string
;
avatar
:
string
}
}
=
{}
{}
;
private
webHost
=
false
private
webHost
=
false
;
public
async
setup
(
option
:
ChatOption
)
{
if
(
!
option
)
{
...
...
@@ -46,11 +46,11 @@ class Chat {
public
getSdk
=
()
=>
{
if
(
this
.
_sdk
==
null
)
return
;
return
this
.
_sdk
();
}
}
;
public
getOrgId
=
()
=>
{
return
this
.
_orgId
();
}
}
;
public
isWebHost
()
{
return
this
.
webHost
;
...
...
xim/logger.ts
View file @
03c9c8d6
import
{
ChatServiceLogger
}
from
"../model"
;
export
class
ChatLoggerService
{
public
static
logger
=
console
...
...
xim/models/user.ts
View file @
03c9c8d6
...
...
@@ -4,10 +4,11 @@ export enum UserType {
Customer
,
// 客户
}
export
default
interface
User
{
type
User
=
{
uid
:
string
;
oid
:
string
;
eid
:
string
;
jwt
:
string
;
userType
:
UserType
;
};;;;;;;;;;
};
export
default
User
;
xim/token.ts
View file @
03c9c8d6
import
{
ChatOption
,
TokenStringGetter
}
from
"./../model"
;
import
{
TokenStringGetter
}
from
"./../model"
;
function
Token
()
{
let
_token
:
TokenStringGetter
;
return
{
...
...
xim/xim.ts
View file @
03c9c8d6
...
...
@@ -12,7 +12,7 @@ wampDebug(true);
const
DefaultMsgPageSize
=
20
;
function
emptyFunc
()
{
return
null
;
}
export
type
MsgListener
=
(
msg
:
Message
)
=>
void
...
...
@@ -58,7 +58,7 @@ export class Xim {
public
async
open
(
url
:
string
,
token
:
TokenStringGetter
)
{
this
.
connectionPending
=
true
;
await
new
Promise
((
success
:
(
p
?:
unknown
)
=>
void
,
failed
)
=>
{
await
new
Promise
((
resolve
:
(
p
?:
unknown
)
=>
void
,
reject
)
=>
{
this
.
paramsForReconnection
=
{
url
,
token
};
this
.
close
();
...
...
@@ -67,15 +67,15 @@ export class Xim {
this
.
client
=
client
;
client
.
onstatuschange
=
(
status
:
any
,
details
:
any
)
=>
{
this
.
onStatusChange
.
call
(
this
,
status
,
details
);
this
.
onStatusChange
(
status
,
details
);
if
(
status
===
"DISCONNECTED"
||
status
===
"CLOSED"
)
{
failed
(
);
reject
(
status
);
}
};
client
.
onconnected
=
()
=>
{
this
.
onConnected
.
apply
(
this
);
success
();
resolve
();
};
client
.
onmsg
=
this
.
handleMsg
.
bind
(
this
);
...
...
@@ -92,15 +92,16 @@ export class Xim {
* token过期或者切换用户登录时,需要设置新的token
*/
public
async
setToken
(
token
:
TokenStringGetter
)
{
const
client
=
this
.
client
!
;
const
client
=
this
.
client
;
if
(
client
==
null
)
return
;
client
.
close
();
client
.
setToken
(
this
.
trimToken
(
await
token
()));
client
.
open
();
}
public
fetchMsgInBox
(
chatId
:
number
,
msgId
:
number
)
{
return
this
.
client
!
.
fetchMsgInBox
(
chatType
,
chatId
,
msgId
);
if
(
this
.
client
==
null
)
return
;
return
this
.
client
.
fetchMsgInBox
(
chatType
,
chatId
,
msgId
);
}
/**
...
...
@@ -113,13 +114,14 @@ export class Xim {
msg
:
string
)
{
this
.
checkConnected
();
return
this
.
client
!
.
sendMsg
(
chatType
,
chatId
,
msgType
,
msg
,
""
,
{});
if
(
this
.
client
==
null
)
return
;
return
this
.
client
.
sendMsg
(
chatType
,
chatId
,
msgType
,
msg
,
""
,
{});
}
public
inputing
(
chatId
:
number
)
{
this
.
checkConnected
();
return
this
.
client
!
.
userInput
(
chatType
,
chatId
);
if
(
this
.
client
==
null
)
return
;
return
this
.
client
.
userInput
(
chatType
,
chatId
);
}
/*
...
...
@@ -127,8 +129,8 @@ export class Xim {
*/
public
fetchChatMembers
(
chat_id
:
number
)
{
this
.
checkConnected
();
return
this
.
client
!
.
fetchChatMembers
(
chat_id
);
if
(
this
.
client
==
null
)
return
;
return
this
.
client
.
fetchChatMembers
(
chat_id
);
}
/**
...
...
@@ -143,7 +145,8 @@ export class Xim {
desc
=
true
):
Promise
<
Message
[]
>
{
this
.
checkConnected
();
const
res
=
await
this
.
client
!
.
fetchChatMsgs
(
chatType
,
chatId
,
{
if
(
this
.
client
==
null
)
return
;
const
res
=
await
this
.
client
.
fetchChatMsgs
(
chatType
,
chatId
,
{
lid
,
rid
,
limit
,
...
...
@@ -283,8 +286,9 @@ export class Xim {
}
private
onConnected
()
{
if
(
this
.
client
==
null
)
return
;
// 连接成功后,需要调用pubUserInfo, 否则服务端会认为此连接无效
this
.
client
!
.
pubUserInfo
(
""
);
this
.
client
.
pubUserInfo
(
""
);
this
.
debug
(
"xim connected"
);
}
...
...
@@ -334,10 +338,12 @@ export class Xim {
}
private
checkConnected
()
{
if
(
!
this
.
client
!
.
connected
)
{
if
(
this
.
client
==
null
)
return
;
if
(
!
this
.
client
.
connected
)
{
try
{
this
.
client
?.
open
();
}
catch
(
e
)
{
// eslint-disable-next-line no-console
console
.
error
(
"checkConnected"
,
e
);
this
.
reOpen
();
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment