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
8128b0d1
authored
Nov 02, 2021
by
Sixong.Zhu
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
move code to uniplat
parent
352ce1d5
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
0 additions
and
489 deletions
components/chat-title.vue
components/create-chat.vue
components/chat-title.vue
deleted
100644 → 0
View file @
352ce1d5
<
template
>
<div
class=
"room-title d-flex justify-content-between align-items-center"
>
<div
class=
"title text-nowrap"
>
{{
chatTitle
}}
<template
v-if=
"chatMembers.length"
>
<span
class=
"members-count"
>
(成员
{{
chatMembers
.
length
}}
人)
</span
>
</
template
>
<
template
v-if=
"!notOnlyCheck"
>
<div
v-if=
"currentChat.is_finish"
class=
"chat-status chat-done"
>
已完成
</div>
<div
v-else
class=
"chat-status"
>
接待中
</div>
</
template
>
</div>
<div
class=
"title-buttons d-flex align-items-center"
>
<el-button
class=
"button"
@
click=
"startReception"
size=
"small"
v-if=
"!isChatMember"
type=
"primary"
:disabled=
"isChatError"
>
我要接待
</el-button
>
<el-button
class=
"button"
@
click=
"showAddMember"
size=
"small"
:disabled=
"isChatError"
>
添加客服
</el-button
>
<el-button
class=
"button"
@
click=
"finishReception"
size=
"small"
v-if=
"isChatMember && operatorType > 25"
type=
"warning"
:disabled=
"isChatError"
>
结束接待
</el-button
>
<el-button
class=
"button"
@
click=
"exitChat"
size=
"small"
v-if=
"isChatMember"
type=
"danger"
:disabled=
"isChatError"
>
退出会话
</el-button
>
<i
v-if=
"close && isSingleChat"
@
click=
"close"
class=
"title-close el-icon-close"
/>
</div>
<ChatCreator
v-if=
"visible"
:selected=
"chatMembersId"
@
submit=
"addMember"
@
hide=
"hideAddMember"
/>
</div>
</template>
<
script
lang=
"ts"
>
import
{
Component
,
Prop
,
Vue
}
from
"vue-property-decorator"
;
import
ChatCreator
from
"@/customer-service/components/create-chat.vue"
;
import
{
ChatStore
,
chatStore
}
from
"@/customer-service/store/model"
;
import
{
ChatRole
}
from
"../model"
;
import
{
ChatChangedEvent
,
ChatEventHandler
,
}
from
"./controller/chat-event-handler"
;
@
Component
({
components
:
{
ChatCreator
}
})
export
default
class
ChatTitle
extends
Vue
{
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
)
private
readonly
chatId
!
:
ChatStore
.
STATE_CHAT_CURRENT_CHAT_ID
;
@
chatStore
.
Getter
(
ChatStore
.
GETTER_CURRENT_CHAT_PRESENT_MEMBERS
)
private
readonly
chatMembers
!
:
ChatStore
.
GETTER_CURRENT_CHAT_PRESENT_MEMBERS
;
@
chatStore
.
State
(
ChatStore
.
STATE_CURRENT_CHAT_TITLE
)
private
readonly
chatTitle
!
:
ChatStore
.
STATE_CURRENT_CHAT_TITLE
;
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_DIALOG_IS_SINGLE
)
private
readonly
isSingleChat
:
ChatStore
.
STATE_CHAT_DIALOG_IS_SINGLE
;
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_IS_CHAT_ERROR
)
private
readonly
chatError
:
ChatStore
.
STATE_CHAT_CURRENT_IS_CHAT_ERROR
;
@
chatStore
.
Action
(
ChatStore
.
ACTION_CHAT_ADD_CS
)
private
readonly
_addCS
!
:
ChatStore
.
ACTION_CHAT_ADD_CS
;
@
chatStore
.
Action
(
ChatStore
.
ACTION_CHAT_START_RECEPTION
)
private
readonly
_startReception
!
:
ChatStore
.
ACTION_CHAT_START_RECEPTION
;
@
chatStore
.
Action
(
ChatStore
.
ACTION_CHAT_FINISH_RECEPTION
)
private
readonly
_finishReception
!
:
ChatStore
.
ACTION_CHAT_FINISH_RECEPTION
;
@
chatStore
.
Action
(
ChatStore
.
ACTION_CHAT_USER_EXIT
)
private
readonly
_userExitChat
!
:
ChatStore
.
ACTION_CHAT_USER_EXIT
;
@
chatStore
.
Action
(
ChatStore
.
ACTION_CHAT_CS_EXIT
)
private
readonly
_csExitChat
!
:
ChatStore
.
ACTION_CHAT_CS_EXIT
;
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_IS_CHAT_MEMBER
)
private
readonly
isChatMember
!
:
ChatStore
.
STATE_CHAT_CURRENT_IS_CHAT_MEMBER
;
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_USER_UID
)
private
readonly
operatorUid
!
:
ChatStore
.
STATE_CHAT_CURRENT_USER_UID
;
@
chatStore
.
State
(
ChatStore
.
STATE_CHAT_CURRENT_USER_TYPE
)
private
readonly
operatorType
!
:
ChatStore
.
STATE_CHAT_CURRENT_USER_TYPE
;
@
chatStore
.
Mutation
(
ChatStore
.
MUTATION_HIDE_CHAT
)
private
readonly
hideChat
:
ChatStore
.
MUTATION_HIDE_CHAT
;
private
get
isChatError
()
{
return
this
.
chatError
===
this
.
chatId
;
}
private
get
chatMembersId
()
{
return
this
.
chatMembers
.
map
((
k
)
=>
+
k
.
eid
);
}
private
visible
=
false
;
private
get
notOnlyCheck
():
boolean
{
return
true
;
}
@
Prop
({
type
:
Function
})
private
close
?:
()
=>
void
;
private
showAddMember
()
{
this
.
visible
=
true
;
}
private
hideAddMember
()
{
this
.
visible
=
false
;
}
private
async
addMember
(
users
:
string
[],
done
:
()
=>
void
)
{
try
{
await
this
.
_addCS
(
users
);
this
.
hideAddMember
();
}
catch
(
error
)
{
console
.
error
(
error
);
}
finally
{
done
();
}
}
private
noop
()
{
return
1
;
}
private
async
exitChat
()
{
this
.
$confirm
(
"确认要退出此会话?"
)
.
then
(
async
()
=>
{
try
{
if
(
+
this
.
operatorType
===
ChatRole
.
Default
)
{
await
this
.
_userExitChat
();
}
else
if
(
+
this
.
operatorType
>
ChatRole
.
Default
)
{
await
this
.
_csExitChat
();
}
this
.
hideChat
();
}
catch
(
error
)
{
console
.
error
(
error
);
}
})
.
catch
(
this
.
noop
);
}
private
async
startReception
()
{
try
{
await
this
.
_startReception
().
then
(()
=>
ChatEventHandler
.
raiseChatChanged
(
ChatChangedEvent
.
Start
,
this
.
chatId
)
);
this
.
$emit
(
"updateActive"
,
"my_receiving"
);
}
catch
(
error
)
{
console
.
error
(
error
);
}
}
private
async
finishReception
()
{
await
this
.
$confirm
(
"确定要结束接待吗?结束接待将会终止客服会话"
,
"提示"
,
{
confirmButtonText
:
"确定"
,
cancelButtonText
:
"取消"
,
type
:
"warning"
,
}
);
await
this
.
_finishReception
().
then
(()
=>
ChatEventHandler
.
raiseChatChanged
(
ChatChangedEvent
.
End
,
this
.
chatId
)
);
this
.
hideChat
();
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.room-title
{
font-size
:
16px
;
padding
:
0
20px
;
height
:
60px
;
min-height
:
60px
;
border-bottom
:
1px
solid
#e1e1e1
;
.title
{
cursor
:
pointer
;
}
.members-count
{
color
:
#666666
;
}
.title-right-arrow
{
font-size
:
10px
;
margin-left
:
10px
;
vertical-align
:
middle
;
color
:
#666
;
}
.title-close
{
color
:
#8d959d
;
cursor
:
pointer
;
margin-left
:
30px
;
}
}
</
style
>
components/create-chat.vue
deleted
100644 → 0
View file @
352ce1d5
<
template
>
<el-dialog
class=
"create-chat"
title=
"添加客服"
:visible=
"true"
@
close=
"hide"
>
<div
class=
"search-bar"
>
<div
class=
"row input-row"
>
<span
class=
"search-title"
>
用户搜索:
</span>
<el-input
class=
"search-input"
v-model=
"searchText"
></el-input>
<el-button
style=
"margin-left: auto"
type=
"primary"
size=
"medium"
@
click=
"search"
>
筛选
</el-button
>
</div>
<div
class=
"row"
>
<GeneralTagSelectForFilter
ref=
"generalTagSelect"
:tagGroups=
"tagGroups"
class=
"tag-group"
></GeneralTagSelectForFilter>
</div>
</div>
<div
class=
"users"
v-loading=
"loading"
>
<div
v-for=
"user in userList"
:key=
"user.id"
class=
"user-con"
@
click=
"onClickUser(user.id)"
:class=
"
{ forbid: forbidden(user.id) }"
>
<avatar
/>
<span
class=
"user-name"
:class=
"
{
isChoosed: isMember(user.id),
}"
>
{{
user
.
name
}}
</span
>
</div>
</div>
<el-pagination
:current-page
.
sync=
"currentPage"
class=
"fs-pager"
layout=
"prev, pager, next"
:total=
"total"
:page-size=
"pageSize"
></el-pagination>
<span
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"hide"
>
取 消
</el-button>
<el-button
type=
"primary"
@
click=
"createChat"
>
确定
</el-button>
</span>
</el-dialog>
</
template
>
<
script
lang=
"ts"
>
import
{
ListEasy
,
ListTypes
,
TagManagerTypes
}
from
"uniplat-sdk"
;
import
{
Component
,
Prop
,
Vue
,
Watch
}
from
"vue-property-decorator"
;
import
buttonThrottle
from
"../utils/button-throttle"
;
import
GeneralTagSelectForFilter
from
"@/components/statistic/GeneralTagSelectForFilter.vue"
;
import
avatar
from
"@/customer-service/components/avatar.vue"
;
import
chat
from
"@/customer-service/xim/index"
;
type
ThenArg
<
T
>
=
T
extends
PromiseLike
<
infer
U
>
?
U
:
T
;
@
Component
({
components
:
{
avatar
,
GeneralTagSelectForFilter
}
})
export
default
class
ChatCreator
extends
Vue
{
@
Prop
({
type
:
Array
,
default
:
()
=>
[]
})
private
selected
!
:
number
[];
@
Watch
(
"currentPage"
)
private
pageChange
()
{
this
.
nextPage
();
}
private
tagGroups
:
TagManagerTypes
.
TagGroup
[]
=
[];
private
searchText
=
""
;
private
currentPage
=
1
;
private
total
=
0
;
private
pageSize
=
15
;
private
selectedUsers
:
number
[]
=
[];
private
userList
:
{
id
:
any
;
name
:
any
;
}[]
=
[];
private
getList
!
:
ThenArg
<
ReturnType
<
ListEasy
[
"query"
]
>>
[
"getList"
];
public
async
created
()
{
await
this
.
getUserList
();
}
private
getSelectedTags
()
{
if
(
this
.
$refs
.
generalTagSelect
)
{
return
(
this
.
$refs
.
generalTagSelect
as
GeneralTagSelectForFilter
).
getSelectedTags
();
}
return
[];
}
private
async
getUserList
(
searchText
:
string
|
null
=
null
)
{
this
.
loading
=
true
;
const
list
=
chat
.
getSdk
().
model
(
"user"
).
list
();
if
(
searchText
)
{
list
.
addFilter
({
property
:
"first_name"
,
value
:
searchText
,
match
:
ListTypes
.
filterMatchType
.
fuzzy
,
});
}
const
{
pageData
,
getList
}
=
await
list
.
query
({
pageIndex
:
this
.
currentPage
,
item_size
:
this
.
pageSize
,
tagFilters
:
this
.
getSelectedTags
(),
});
this
.
total
=
pageData
.
record_count
;
this
.
getList
=
getList
;
this
.
userList
=
this
.
exactUserList
(
pageData
.
rows
);
this
.
loading
=
false
;
this
.
tagGroups
=
pageData
.
tagGroups
||
[];
}
private
exactUserList
(
rows
:
any
[])
{
return
rows
.
map
((
k
)
=>
{
return
{
id
:
k
.
id
.
value
,
name
:
k
.
first_name
.
value
,
};
});
}
private
hide
()
{
this
.
$emit
(
"hide"
);
}
private
search
()
{
this
.
currentPage
=
1
;
this
.
getUserList
(
this
.
searchText
);
}
private
loading
=
false
;
@
buttonThrottle
()
private
async
nextPage
()
{
this
.
loading
=
true
;
const
data
=
await
this
.
getList
(
this
.
currentPage
);
this
.
loading
=
false
;
this
.
userList
=
this
.
exactUserList
(
data
.
rows
);
}
private
forbidden
(
id
:
number
)
{
return
this
.
selected
.
includes
(
id
);
}
private
isMember
(
id
:
number
)
{
return
this
.
selectedUsers
.
includes
(
id
)
||
this
.
selected
.
includes
(
id
);
}
private
isSelected
(
id
:
number
)
{
return
this
.
selectedUsers
.
includes
(
id
);
}
private
onClickUser
(
id
:
number
)
{
if
(
this
.
isSelected
(
id
))
{
this
.
removeUser
(
id
);
}
else
{
this
.
addUser
(
id
);
}
}
private
addUser
(
id
:
number
)
{
this
.
selectedUsers
.
push
(
id
);
}
private
removeUser
(
id
:
number
)
{
this
.
selectedUsers
=
this
.
selectedUsers
.
filter
((
_id
)
=>
_id
!==
id
);
}
@
buttonThrottle
()
private
createChat
()
{
return
new
Promise
((
resolve
)
=>
{
this
.
$emit
(
"submit"
,
this
.
selectedUsers
.
map
((
id
)
=>
String
(
id
)),
resolve
);
});
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.text-right
{
text-align
:
right
;
}
.create-chat
{
/deep/
.el-dialog__body
{
padding
:
30px
40px
;
}
}
.users
{
white-space
:
pre-line
;
}
.user-con
{
display
:
inline-flex
;
vertical-align
:
top
;
width
:
33.33%
;
align-items
:
center
;
margin-bottom
:
40px
;
cursor
:
pointer
;
&.forbid
{
cursor
:
not-allowed
;
}
}
.user-name
{
height
:
15px
;
font-size
:
15px
;
color
:
#000000
;
line-height
:
15px
;
margin-left
:
20px
;
&.isChoosed
{
color
:
#3285ff
;
}
}
.search-bar
{
align-items
:
center
;
background
:
#f5f6fa
;
padding
:
12px
20px
;
box-sizing
:
border-box
;
margin-bottom
:
30px
;
.row
+
.row
{
margin-top
:
5px
;
}
.tag-group
/
deep
/
.checkbox-group
{
padding
:
0
;
margin-bottom
:
0
;
}
.input-row
{
display
:
flex
;
line-height
:
40px
;
}
}
.search-input
{
width
:
160px
;
margin-left
:
10px
;
/deep/
.el-input__inner
{
border
:
1px
solid
rgba
(
229
,
230
,
236
,
1
);
border-radius
:
0
;
padding-left
:
21px
;
}
}
</
style
>
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