Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
杨树贤
/
kefu_server
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
e3a7f5bd
authored
Mar 22, 2020
by
chenxianqi
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
update code
parent
825ca73b
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
469 additions
and
182 deletions
controllers/public_controller.go
routers/router.go
ui/kefu_client/plugins/help.js
ui/kefu_client/plugins/mimc.js
ui/kefu_client/src/App.vue
ui/kefu_client/src/assets/workorder.png
ui/kefu_client/src/router.js
ui/kefu_client/src/store/actions.js
ui/kefu_client/src/store/getters.js
ui/kefu_client/src/store/state.js
ui/kefu_client/src/views/kefu.vue
ui/kefu_client/src/views/workorder.vue
ui/kefu_client/src/views/workorder_detail.vue
controllers/public_controller.go
View file @
e3a7f5bd
...
@@ -601,6 +601,13 @@ func (c *PublicController) CreateWorkOrder() {
...
@@ -601,6 +601,13 @@ func (c *PublicController) CreateWorkOrder() {
c
.
JSON
(
configs
.
ResponseFail
,
err
.
Message
,
nil
)
c
.
JSON
(
configs
.
ResponseFail
,
err
.
Message
,
nil
)
}
}
}
}
// type is exist?
workOrderTypeRepository
:=
services
.
GetWorkOrderTypeRepositoryInstance
()
if
_
,
err
:=
workOrderTypeRepository
.
GetWorkOrderType
(
workOrder
.
CID
);
err
!=
nil
{
c
.
JSON
(
configs
.
ResponseFail
,
"创建失败,工单类型不存在~"
,
err
.
Error
())
}
workOrder
.
CreateAt
=
time
.
Now
()
.
Unix
()
workOrder
.
CreateAt
=
time
.
Now
()
.
Unix
()
workOrder
.
UID
=
user
.
ID
workOrder
.
UID
=
user
.
ID
workOrderRepository
:=
services
.
GetWorkOrderRepositoryInstance
()
workOrderRepository
:=
services
.
GetWorkOrderRepositoryInstance
()
...
@@ -711,6 +718,20 @@ func (c *PublicController) GetWorkOrders() {
...
@@ -711,6 +718,20 @@ func (c *PublicController) GetWorkOrders() {
}
}
// GetWorkOrderTypes user get word order type all
func
(
c
*
PublicController
)
GetWorkOrderTypes
()
{
// get user
user
:=
c
.
GetUserInfo
()
if
user
==
nil
{
c
.
JSON
(
configs
.
ResponseFail
,
"查询失败!"
,
nil
)
}
workOrderTypeRepository
:=
services
.
GetWorkOrderTypeRepositoryInstance
()
workOrderTypes
:=
workOrderTypeRepository
.
GetWorkOrderTypes
()
c
.
JSON
(
configs
.
ResponseSucess
,
"查询成功!"
,
workOrderTypes
)
}
// GetWorkOrderComments get word order comments
// GetWorkOrderComments get word order comments
func
(
c
*
PublicController
)
GetWorkOrderComments
()
{
func
(
c
*
PublicController
)
GetWorkOrderComments
()
{
...
...
routers/router.go
View file @
e3a7f5bd
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
// @Description kefu server APIs.
// @Description kefu server APIs.
// @Contact 361554012@qq.com
// @Contact 361554012@qq.com
package
routers
package
routers
import
(
import
(
"kefu_server/controllers"
"kefu_server/controllers"
...
@@ -51,6 +51,7 @@ func init() {
...
@@ -51,6 +51,7 @@ func init() {
beego
.
NSRouter
(
"/workorder/create"
,
&
controllers
.
PublicController
{},
"post:CreateWorkOrder"
),
beego
.
NSRouter
(
"/workorder/create"
,
&
controllers
.
PublicController
{},
"post:CreateWorkOrder"
),
beego
.
NSRouter
(
"/workorder/reply"
,
&
controllers
.
PublicController
{},
"post:ReplyWorkOrder"
),
beego
.
NSRouter
(
"/workorder/reply"
,
&
controllers
.
PublicController
{},
"post:ReplyWorkOrder"
),
beego
.
NSRouter
(
"/workorders"
,
&
controllers
.
PublicController
{},
"get:GetWorkOrders"
),
beego
.
NSRouter
(
"/workorders"
,
&
controllers
.
PublicController
{},
"get:GetWorkOrders"
),
beego
.
NSRouter
(
"/workorder/types"
,
&
controllers
.
PublicController
{},
"get:GetWorkOrderTypes"
),
beego
.
NSRouter
(
"/workorder/comments/:wid"
,
&
controllers
.
PublicController
{},
"get:GetWorkOrderComments"
),
beego
.
NSRouter
(
"/workorder/comments/:wid"
,
&
controllers
.
PublicController
{},
"get:GetWorkOrderComments"
),
beego
.
NSRouter
(
"/workorder/:wid"
,
&
controllers
.
PublicController
{},
"get:GetWorkOrder"
),
beego
.
NSRouter
(
"/workorder/:wid"
,
&
controllers
.
PublicController
{},
"get:GetWorkOrder"
),
beego
.
NSRouter
(
"/workorder/:wid"
,
&
controllers
.
PublicController
{},
"delete:DeleteWorkOrder"
),
beego
.
NSRouter
(
"/workorder/:wid"
,
&
controllers
.
PublicController
{},
"delete:DeleteWorkOrder"
),
...
...
ui/kefu_client/plugins/help.js
View file @
e3a7f5bd
...
@@ -18,6 +18,10 @@ Helps.install = function (Vue, options) {
...
@@ -18,6 +18,10 @@ Helps.install = function (Vue, options) {
}
}
return
moment
(
parseInt
(
unix
+
'000'
)).
format
(
format
)
return
moment
(
parseInt
(
unix
+
'000'
)).
format
(
format
)
}
}
// 格式化日期(相对日期)
Vue
.
prototype
.
$formatDate
=
function
(
unix
,
format
=
"YYYY-MM-DD HH:mm:ss"
)
{
return
moment
(
parseInt
(
unix
+
'000'
)).
format
(
format
)
}
Vue
.
prototype
.
$robotNickname
=
function
(
id
)
{
Vue
.
prototype
.
$robotNickname
=
function
(
id
)
{
var
nickname
var
nickname
var
robots
=
this
.
$store
.
getters
.
robots
var
robots
=
this
.
$store
.
getters
.
robots
...
...
ui/kefu_client/plugins/mimc.js
View file @
e3a7f5bd
...
@@ -36,20 +36,22 @@ MimcPlugin.install = function (Vue, options) {
...
@@ -36,20 +36,22 @@ MimcPlugin.install = function (Vue, options) {
localStorage
.
setItem
(
"user"
,
JSON
.
stringify
(
response
.
data
.
data
.
user
))
localStorage
.
setItem
(
"user"
,
JSON
.
stringify
(
response
.
data
.
data
.
user
))
localStorage
.
setItem
(
"Token"
,
response
.
data
.
data
.
user
.
token
)
localStorage
.
setItem
(
"Token"
,
response
.
data
.
data
.
user
.
token
)
console
.
log
(
"MIMC初始化成功"
)
console
.
log
(
"MIMC初始化成功"
)
this
.
getRobot
()
this
.
getRobot
(()
=>
{
if
(
callback
)
callback
(
response
.
data
.
data
.
user
)
if
(
callback
)
callback
(
response
.
data
.
data
.
user
)
})
})
})
.
catch
((
error
)
=>
{
.
catch
((
error
)
=>
{
if
(
callback
)
callback
(
null
)
if
(
callback
)
callback
(
null
)
console
.
log
(
error
.
response
)
console
.
log
(
error
)
})
})
},
},
// 获取机器人
// 获取机器人
getRobot
(){
getRobot
(
callback
){
axios
.
get
(
'/public/robot/'
+
this
.
platform
)
axios
.
get
(
'/public/robot/'
+
this
.
platform
)
.
then
(
response
=>
{
.
then
(
response
=>
{
this
.
robot
=
response
.
data
.
data
this
.
robot
=
response
.
data
.
data
})
if
(
callback
)
callback
()
})
.
catch
((
error
)
=>
{
.
catch
((
error
)
=>
{
console
.
log
(
"mimc初始化失败,请刷新重试"
,
error
)
console
.
log
(
"mimc初始化失败,请刷新重试"
,
error
)
})
})
...
...
ui/kefu_client/src/App.vue
View file @
e3a7f5bd
<
template
>
<
template
>
<div>
<div>
<router-view
/>
<div
class=
"mini-im-loading"
:class=
"
{'pc-mini-im-loading': !isMobile}"
v-if="isShowPageLoading"
>
<mt-spinner
type=
"triple-bounce"
color=
"#26a2ff"
></mt-spinner>
</div>
</div>
<router-view
/>
</div>
</
template
>
</
template
>
<
script
>
<
script
>
import
{
mapGetters
}
from
"vuex"
;
export
default
{
export
default
{
name
:
"app"
,
name
:
"app"
,
data
()
{
data
()
{
return
{
return
{};
};
},
},
computed
:
{
computed
:
{
...
mapGetters
([
"isShowPageLoading"
,
"userAccount"
,
"isArtificial"
,
"isMobile"
,
"artificialAccount"
,
"robotAccount"
,
"platform"
,
"userLocal"
,
"uid"
,
"uid"
,
])
},
},
mounted
()
{
created
()
{
this
.
handelUrl
()
this
.
getLocal
();
setTimeout
(()
=>
{
this
.
handelUrl
()
this
.
runApp
()
},
500
);
// 判断是否被踢出对话
this
.
onCheckIsOutSession
();
},
},
methods
:
{
methods
:
{
runApp
()
{
const
user
=
this
.
$mimcInstance
.
getLocalCacheUser
();
if
(
user
&&
this
.
userAccount
!=
null
&&
this
.
userAccount
!=
user
.
id
&&
this
.
userAccount
!=
0
)
{
localStorage
.
clear
();
}
this
.
$mimcInstance
.
init
(
{
type
:
0
,
// 默认0
address
:
this
.
userLocal
,
uid
:
this
.
uid
||
0
,
// 预留字段扩展自己平台业务
platform
:
this
.
platform
,
// 渠道(平台)
account_id
:
this
.
userAccount
||
0
// 用户ID
// 初始化完成这里返回一个user
},
user
=>
{
// 上报活动时间
this
.
upLastActivity
();
// 获取公司信息
this
.
$store
.
dispatch
(
"onGetCompanyInfo"
);
// 获取上传配置信息
this
.
$store
.
dispatch
(
"onGetUploadSecret"
);
// 获取工单类型
this
.
$store
.
dispatch
(
"onGetWorkorderTypes"
);
// 获取工单列表
this
.
$store
.
dispatch
(
"onGetWorkorders"
);
// 重试
if
(
!
user
)
{
setTimeout
(()
=>
this
.
runApp
(),
1000
);
return
;
}
// user
this
.
$store
.
commit
(
"updateState"
,
{
userAccount
:
user
.
id
,
userInfo
:
user
});
// robot
var
robot
=
this
.
$mimcInstance
.
robot
;
localStorage
.
setItem
(
"robot_"
+
robot
.
id
,
JSON
.
stringify
(
robot
));
this
.
$store
.
commit
(
"updateState"
,
{
robotAccount
:
robot
.
id
,
robotInfo
:
robot
});
// 登录mimc
this
.
$mimcInstance
.
login
();
// 发送一条握手消息给机器人
var
sentHandshake
=
()
=>
{
if
(
this
.
$mimcInstance
.
user
==
null
||
!
this
.
$mimcInstance
.
user
.
isLogin
())
{
setTimeout
(()
=>
sentHandshake
(),
200
);
return
}
if
(
!
this
.
artificialAccount
)
{
console
.
log
(
"握手消息"
);
this
.
$mimcInstance
.
sendMessage
(
"handshake"
,
this
.
robotAccount
,
""
);
}
}
sentHandshake
()
}
);
},
// Handelurl
// Handelurl
handelUrl
()
{
handelUrl
()
{
// url query 介绍
// url query 介绍
...
@@ -30,8 +133,15 @@ export default {
...
@@ -30,8 +133,15 @@ export default {
// u == userAccount 会话用户账号
// u == userAccount 会话用户账号
// uid == userId 业务平台的ID
// uid == userId 业务平台的ID
// c = 1 清除本地缓存
// c = 1 清除本地缓存
var
isShowHeader
,
isMobile
,
userAccount
,
uid
,
isArtificial
,
artificialAccount
,
robotAccount
,
platform
var
isShowHeader
,
var
query
=
this
.
queryToJson
(
location
.
search
);
isMobile
,
userAccount
,
uid
,
isArtificial
,
artificialAccount
,
robotAccount
,
platform
;
var
query
=
this
.
$route
.
query
;
if
(
query
&&
query
.
c
)
localStorage
.
clear
();
if
(
query
&&
query
.
c
)
localStorage
.
clear
();
// 获取本地缓存
// 获取本地缓存
var
urlQuery
=
this
.
queryToJson
(
localStorage
.
getItem
(
"urlQuery"
));
var
urlQuery
=
this
.
queryToJson
(
localStorage
.
getItem
(
"urlQuery"
));
...
@@ -48,19 +158,28 @@ export default {
...
@@ -48,19 +158,28 @@ export default {
if
(
query
.
p
)
platform
=
parseInt
(
query
.
p
);
if
(
query
.
p
)
platform
=
parseInt
(
query
.
p
);
if
(
query
.
uid
)
uid
=
parseInt
(
query
.
uid
);
if
(
query
.
uid
)
uid
=
parseInt
(
query
.
uid
);
if
(
query
.
r
==
"0"
)
{
if
(
query
.
r
==
"0"
)
{
isArtificial
=
true
isArtificial
=
true
;
artificialAccount
=
parseInt
(
query
.
a
)
artificialAccount
=
parseInt
(
query
.
a
);
}
else
{
}
else
{
robotAccount
=
parseInt
(
query
.
a
)
robotAccount
=
parseInt
(
query
.
a
);
}
}
}
}
var
isArtificialString
=
localStorage
.
getItem
(
"isArtificial"
);
var
isArtificialString
=
localStorage
.
getItem
(
"isArtificial"
);
var
artificialAccountString
=
localStorage
.
getItem
(
"artificialAccount"
);
var
artificialAccountString
=
localStorage
.
getItem
(
"artificialAccount"
);
if
(
isArtificialString
==
"true"
)
{
if
(
isArtificialString
==
"true"
)
{
isArtificial
=
true
isArtificial
=
true
;
artificialAccount
=
parseInt
(
artificialAccountString
)
artificialAccount
=
parseInt
(
artificialAccountString
);
}
}
this
.
$store
.
commit
(
"updateState"
,
{
isShowHeader
,
isMobile
,
userAccount
,
uid
,
isArtificial
,
artificialAccount
,
robotAccount
,
platform
})
this
.
$store
.
commit
(
"updateState"
,
{
isShowHeader
,
isMobile
,
userAccount
,
uid
,
isArtificial
,
artificialAccount
,
robotAccount
,
platform
});
},
},
// query 转json
// query 转json
queryToJson
(
str
)
{
queryToJson
(
str
)
{
...
@@ -74,7 +193,33 @@ export default {
...
@@ -74,7 +193,33 @@ export default {
}
}
return
mapData
;
return
mapData
;
},
},
// 根据IP获取用户地理位置
getLocal
()
{
this
.
$store
.
dispatch
(
"onGetLocal"
,
this
.
$store
.
state
.
AmapAPPKey
);
},
// 上报最后活动时间
upLastActivity
()
{
this
.
onCheckIsOutSession
();
const
user
=
this
.
$mimcInstance
.
getLocalCacheUser
();
if
(
user
)
this
.
$store
.
dispatch
(
"onUpdateLastActivity"
);
if
(
this
.
isArtificial
)
{
localStorage
.
setItem
(
"artificialTime"
,
Date
.
now
());
}
setTimeout
(()
=>
this
.
upLastActivity
(),
1000
*
60
);
},
// 判断是否被踢出对话
onCheckIsOutSession
()
{
var
artificialTime
=
localStorage
.
getItem
(
"artificialTime"
);
if
(
artificialTime
)
{
artificialTime
=
parseInt
(
artificialTime
);
if
(
Date
.
now
()
>
artificialTime
+
60
*
1000
*
10
)
{
this
.
$store
.
commit
(
"updateState"
,
{
isArtificial
:
false
,
artificialAccount
:
null
});
}
}
},
}
}
};
};
</
script
>
</
script
>
...
@@ -114,5 +259,26 @@ body {
...
@@ -114,5 +259,26 @@ body {
font-size
:
23px
!important
;
font-size
:
23px
!important
;
}
}
.mini-im-loading
{
display
:
flex
;
width
:
100%
;
position
:
fixed
;
height
:
100vh
;
top
:
0
;
left
:
0
;
z-index
:
9
;
right
:
0
;
background-color
:
#fff
!important
;
margin
:
auto
;
align-items
:
center
;
justify-content
:
center
;
&.pc-mini-im-loading
{
width
:
360px
!important
;
height
:
360px
!important
;
top
:
-48px
;
bottom
:
0
;
margin
:
auto
!important
;
}
}
</
style
>
</
style
>
ui/kefu_client/src/assets/workorder.png
View file @
e3a7f5bd
391 Bytes
|
W:
|
H:
1.1 KB
|
W:
|
H:
2-up
Swipe
Onion skin
ui/kefu_client/src/router.js
View file @
e3a7f5bd
...
@@ -25,7 +25,7 @@ const router = new Router({
...
@@ -25,7 +25,7 @@ const router = new Router({
component
:
()
=>
import
(
'./views/workorder_create.vue'
)
component
:
()
=>
import
(
'./views/workorder_create.vue'
)
},
},
{
{
path
:
'/workorder/detail'
,
path
:
'/workorder/detail
/:id
'
,
name
:
'workorder_detail'
,
name
:
'workorder_detail'
,
component
:
()
=>
import
(
'./views/workorder_detail.vue'
)
component
:
()
=>
import
(
'./views/workorder_detail.vue'
)
},
},
...
...
ui/kefu_client/src/store/actions.js
View file @
e3a7f5bd
...
@@ -14,13 +14,15 @@ export default {
...
@@ -14,13 +14,15 @@ export default {
.
then
(
response
=>
{
.
then
(
response
=>
{
let
newMessage
=
[];
let
newMessage
=
[];
let
messages
=
response
.
data
.
data
.
list
||
[];
let
messages
=
response
.
data
.
data
.
list
||
[];
if
(
messages
.
length
<
pageSize
)
{
if
(
messages
.
length
<
pageSize
||
messages
.
length
==
0
)
{
context
.
commit
(
'updateState'
,
{
isLoadMorEnd
:
true
})
context
.
commit
(
'updateState'
,
{
isLoadMorEnd
:
true
})
}
}
if
(
params
.
oldMsg
.
length
==
0
&&
messages
.
length
>
0
)
{
if
(
params
.
oldMsg
.
length
==
0
&&
messages
.
length
>
0
)
{
newMessage
=
response
.
data
.
data
.
list
newMessage
=
response
.
data
.
data
.
list
}
else
if
(
messages
.
length
>
0
)
{
}
else
if
(
messages
.
length
>
0
)
{
newMessage
=
messages
.
concat
(
params
.
oldMsg
);
newMessage
=
messages
.
concat
(
params
.
oldMsg
);
}
else
{
newMessage
=
params
.
oldMsg
}
}
context
.
commit
(
'updateState'
,
{
messages
:
newMessage
})
context
.
commit
(
'updateState'
,
{
messages
:
newMessage
})
if
(
params
.
callback
)
params
.
callback
()
if
(
params
.
callback
)
params
.
callback
()
...
@@ -71,5 +73,17 @@ export default {
...
@@ -71,5 +73,17 @@ export default {
axios
.
get
(
"/public/secret"
).
then
(
response
=>
{
axios
.
get
(
"/public/secret"
).
then
(
response
=>
{
context
.
commit
(
'updateState'
,
{
uploadToken
:
response
.
data
.
data
})
context
.
commit
(
'updateState'
,
{
uploadToken
:
response
.
data
.
data
})
});
});
},
// 获取工单类型
onGetWorkorderTypes
(
context
){
axios
.
get
(
"/public/workorder/types"
).
then
(
response
=>
{
context
.
commit
(
'updateState'
,
{
workorderTypes
:
response
.
data
.
data
})
});
},
// 获取工单列表
onGetWorkorders
(
context
){
axios
.
get
(
"/public/workorders"
).
then
(
response
=>
{
context
.
commit
(
'updateState'
,
{
workorders
:
response
.
data
.
data
})
});
}
}
}
}
\ No newline at end of file
ui/kefu_client/src/store/getters.js
View file @
e3a7f5bd
...
@@ -62,5 +62,14 @@ export default {
...
@@ -62,5 +62,14 @@ export default {
let
limit
=
window
.
screen
.
height
==
window
.
screen
.
availHeight
?
1.8
:
1.65
;
let
limit
=
window
.
screen
.
height
==
window
.
screen
.
availHeight
?
1.8
:
1.65
;
if
(
rate
>
limit
)
yes
=
true
;
if
(
rate
>
limit
)
yes
=
true
;
return
yes
;
return
yes
;
},
isShowPageLoading
(
state
){
return
state
.
isShowPageLoading
},
workorders
(
state
){
return
state
.
workorders
},
workorderTypes
(
state
){
return
state
.
workorderTypes
}
}
}
}
\ No newline at end of file
ui/kefu_client/src/store/state.js
View file @
e3a7f5bd
export
default
{
export
default
{
platform
:
5
,
// 平台(渠道)
platform
:
5
,
// 平台(渠道)
isShowPageLoading
:
false
,
// page loading
isShowHeader
:
true
,
// 是否显示header
isShowHeader
:
true
,
// 是否显示header
isMobile
:
true
,
// 是否是移动端
isMobile
:
true
,
// 是否是移动端
isArtificial
:
false
,
// 是否是人工服务
isArtificial
:
false
,
// 是否是人工服务
...
@@ -16,4 +17,9 @@ export default {
...
@@ -16,4 +17,9 @@ export default {
userInfo
:
{},
// 用户信息
userInfo
:
{},
// 用户信息
companyInfo
:
null
,
// 公司信息
companyInfo
:
null
,
// 公司信息
uploadToken
:
null
,
// 上传token
uploadToken
:
null
,
// 上传token
// workorder
workorders
:
[],
// 工单列表
workorderTypes
:
[],
// 工单类型列表
}
}
\ No newline at end of file
ui/kefu_client/src/views/kefu.vue
View file @
e3a7f5bd
...
@@ -162,9 +162,6 @@
...
@@ -162,9 +162,6 @@
<span>
正在连接中~
</span>
<span>
正在连接中~
</span>
</div>
</div>
</div>
</div>
<div
class=
"mini-im-loading"
v-if=
"isLoading"
>
<mt-spinner
type=
"triple-bounce"
color=
"#26a2ff"
></mt-spinner>
</div>
<div
class=
"mini-im-emoji"
v-show=
"showEmoji"
>
<div
class=
"mini-im-emoji"
v-show=
"showEmoji"
>
<div
class=
"mini-im-emoji-content"
>
<div
class=
"mini-im-emoji-content"
>
<span
@
click=
"()=>clickEmoji(item)"
v-for=
"(item, index) in emojis"
:key=
"index"
>
{{item}}
</span>
<span
@
click=
"()=>clickEmoji(item)"
v-for=
"(item, index) in emojis"
:key=
"index"
>
{{item}}
</span>
...
@@ -196,7 +193,11 @@
...
@@ -196,7 +193,11 @@
<span
class=
"expression-btn"
@
click=
"showEmoji = !showEmoji"
>
<span
class=
"expression-btn"
@
click=
"showEmoji = !showEmoji"
>
<img
src=
"../assets/expression.png"
alt
/>
<img
src=
"../assets/expression.png"
alt
/>
</span>
</span>
<span
class=
"workorder-btn"
@
click=
"$router.push('/workorder')"
>
<span
class=
"workorder-btn"
:class=
"{'show-header': !isShowHeader && isMobile}"
@
click=
"$router.push('/workorder')"
>
<img
src=
"../assets/workorder.png"
/>
<img
src=
"../assets/workorder.png"
/>
<i>
工单
</i>
<i>
工单
</i>
</span>
</span>
...
@@ -236,8 +237,7 @@ export default {
...
@@ -236,8 +237,7 @@ export default {
name
:
"app"
,
name
:
"app"
,
data
()
{
data
()
{
return
{
return
{
isLoading
:
true
,
isShowTopLoading
:
false
,
// top loading is connect loading
isShowTopLoading
:
true
,
isFirstGetMessage
:
true
,
// 第一次获取本地消息
isFirstGetMessage
:
true
,
// 第一次获取本地消息
chatValue
:
""
,
// 发送消息的内容
chatValue
:
""
,
// 发送消息的内容
emojis
:
emojiService
.
emojiData
,
// emoji数据
emojis
:
emojiService
.
emojiData
,
// emoji数据
...
@@ -254,8 +254,7 @@ export default {
...
@@ -254,8 +254,7 @@ export default {
};
};
},
},
created
()
{
created
()
{
// this.getLocal()
this
.
init
();
this
.
runApp
();
},
},
computed
:
{
computed
:
{
account
()
{
account
()
{
...
@@ -296,8 +295,10 @@ export default {
...
@@ -296,8 +295,10 @@ export default {
])
])
},
},
mounted
()
{
mounted
()
{
document
.
title
=
"在线客服"
setTimeout
(()
=>
{
setTimeout
(()
=>
{
this
.
isLoading
=
true
;
this
.
scroll
=
new
BScroll
(
this
.
$refs
.
miniImBody
,
{
this
.
scroll
=
new
BScroll
(
this
.
$refs
.
miniImBody
,
{
click
:
true
,
click
:
true
,
tab
:
true
,
tab
:
true
,
...
@@ -312,93 +313,56 @@ export default {
...
@@ -312,93 +313,56 @@ export default {
this
.
loadMorData
();
this
.
loadMorData
();
}
}
});
});
// 监听发送按钮触摸事件
// 监听发送按钮触摸事件
this
.
addSendButtonTouchEventListener
();
this
.
addSendButtonTouchEventListener
();
this
.
createLinkQuery
();
this
.
createLinkQuery
();
this
.
scrollIntoBottom
();
this
.
scrollIntoBottom
();
},
500
);
},
500
);
// 判断是否被踢出对话
this
.
onCheckIsOutSession
();
// 粘贴事件
// 粘贴事件
document
.
addEventListener
(
"paste"
,
this
.
inputPaste
,
false
);
document
.
addEventListener
(
"paste"
,
this
.
inputPaste
,
false
);
},
},
beforeDestroy
()
{
beforeDestroy
()
{
this
.
$store
.
dispatch
(
"onToggleWindow"
,
0
);
this
.
$store
.
dispatch
(
"onToggleWindow"
,
0
);
},
},
methods
:
{
methods
:
{
// runApp
// init
runApp
()
{
init
()
{
const
user
=
this
.
$mimcInstance
.
getLocalCacheUser
();
this
.
$store
.
commit
(
"updateState"
,
{
isShowPageLoading
:
true
});
if
(
user
&&
// 重试
this
.
userAccount
!=
null
&&
if
(
this
.
$mimcInstance
.
user
==
null
||
!
this
.
$mimcInstance
.
user
.
isLogin
())
{
this
.
userAccount
!=
user
.
id
&&
setTimeout
(()
=>
this
.
init
(),
1000
);
this
.
userAccount
!=
0
return
)
{
localStorage
.
clear
();
}
}
this
.
$mimcInstance
.
init
(
{
// handelEvent
type
:
0
,
// 默认0
this
.
handelEvent
();
address
:
this
.
userLocal
,
uid
:
this
.
uid
||
0
,
// 预留字段扩展自己平台业务
// 清除未读消息
platform
:
this
.
platform
,
// 渠道(平台)
this
.
$store
.
dispatch
(
"onCleanRead"
);
account_id
:
this
.
userAccount
||
0
// 用户ID
// 初始化完成这里返回一个user
// 更换toggle
},
this
.
$store
.
dispatch
(
"onToggleWindow"
,
1
);
user
=>
{
if
(
!
user
)
{
// 获取消息记录
setTimeout
(()
=>
this
.
runApp
(),
1000
);
this
.
getMessageRecord
();
}
else
{
this
.
isLoading
=
false
;
// handelEvent
this
.
scrollIntoBottom
();
this
.
handelEvent
();
// user
// 关闭loading
this
.
$store
.
commit
(
"updateState"
,
{
userAccount
:
user
.
id
,
userInfo
:
user
});
setTimeout
(()
=>
this
.
$store
.
commit
(
"updateState"
,
{
isShowPageLoading
:
false
}),
500
)
// robot
var
robot
=
this
.
$mimcInstance
.
robot
;
console
.
log
(
robot
);
localStorage
.
setItem
(
"robot_"
+
robot
.
id
,
JSON
.
stringify
(
robot
));
this
.
$store
.
commit
(
"updateState"
,
{
robotAccount
:
robot
.
id
,
robotInfo
:
robot
});
// 清除未读消息
this
.
$store
.
dispatch
(
"onCleanRead"
);
// 更换toggle
this
.
$store
.
dispatch
(
"onToggleWindow"
,
1
);
// 登录完成发送一条握手消息给机器人
this
.
$mimcInstance
.
login
(()
=>
{
setTimeout
(()
=>
{
// 获取消息记录
this
.
getMessageRecord
();
if
(
!
this
.
artificialAccount
)
{
console
.
log
(
"握手消息"
);
this
.
$mimcInstance
.
sendMessage
(
"handshake"
,
this
.
robotAccount
,
""
);
}
this
.
scrollIntoBottom
();
},
500
);
});
}
}
);
// 计算客服最后回复时间
// 计算客服最后回复时间
this
.
onServciceLastMessageTimeNotCallBack
();
this
.
onServciceLastMessageTimeNotCallBack
();
},
},
// handelEvent
// handelEvent
handelEvent
()
{
handelEvent
()
{
// 获取公司信息
this
.
$store
.
dispatch
(
"onGetCompanyInfo"
)
// 获取上传配置信息
this
.
$store
.
dispatch
(
"onGetUploadSecret"
)
// 上报活动时间
this
.
upLastActivity
();
// 监听消息
// 监听消息
this
.
$mimcInstance
.
addEventListener
(
"receiveP2PMsg"
,
this
.
receiveP2PMsg
);
this
.
$mimcInstance
.
addEventListener
(
"receiveP2PMsg"
,
this
.
receiveP2PMsg
);
...
@@ -414,6 +378,9 @@ export default {
...
@@ -414,6 +378,9 @@ export default {
this
.
$mimcInstance
.
addEventListener
(
this
.
$mimcInstance
.
addEventListener
(
"statusChange"
,
"statusChange"
,
(
bindResult
,
errType
,
errReason
,
errDesc
)
=>
{
(
bindResult
,
errType
,
errReason
,
errDesc
)
=>
{
if
(
bindResult
)
{
this
.
isShowTopLoading
=
false
;
}
console
.
log
(
"状态发生变化"
,
bindResult
,
errType
,
errReason
,
errDesc
);
console
.
log
(
"状态发生变化"
,
bindResult
,
errType
,
errReason
,
errDesc
);
}
}
);
);
...
@@ -438,13 +405,9 @@ export default {
...
@@ -438,13 +405,9 @@ export default {
this
.
onCheckIsloogTimeNotCallBack
();
this
.
onCheckIsloogTimeNotCallBack
();
// 关闭top loading
// 关闭top loading
setTimeout
(()
=>
this
.
isShowTopLoading
=
false
,
1000
)
setTimeout
(()
=>
(
this
.
isShowTopLoading
=
false
),
1000
);
},
},
// 根据IP获取用户地理位置
getLocal
()
{
this
.
$store
.
dispatch
(
"onGetLocal"
,
this
.
$store
.
state
.
AmapAPPKey
);
},
// 快捷键换行
// 快捷键换行
enterShift
(
event
)
{
enterShift
(
event
)
{
if
(
this
.
isMobile
)
return
;
if
(
this
.
isMobile
)
return
;
...
@@ -499,29 +462,6 @@ export default {
...
@@ -499,29 +462,6 @@ export default {
window
.
open
(
url
);
window
.
open
(
url
);
}
}
},
},
// 上报最后活动时间
upLastActivity
()
{
this
.
onCheckIsOutSession
();
const
user
=
this
.
$mimcInstance
.
getLocalCacheUser
();
if
(
user
)
this
.
$store
.
dispatch
(
"onUpdateLastActivity"
);
if
(
this
.
isArtificial
)
{
localStorage
.
setItem
(
"artificialTime"
,
Date
.
now
());
}
setTimeout
(()
=>
this
.
upLastActivity
(),
1000
*
60
);
},
// 判断是否被踢出对话
onCheckIsOutSession
()
{
var
artificialTime
=
localStorage
.
getItem
(
"artificialTime"
);
if
(
artificialTime
)
{
artificialTime
=
parseInt
(
artificialTime
);
if
(
Date
.
now
()
>
artificialTime
+
60
*
1000
*
10
)
{
this
.
$store
.
commit
(
"updateState"
,
{
isArtificial
:
false
,
artificialAccount
:
null
});
}
}
},
// 获取更多数据
// 获取更多数据
loadMorData
()
{
loadMorData
()
{
if
(
this
.
isLoadMorLoading
)
return
;
if
(
this
.
isLoadMorLoading
)
return
;
...
@@ -613,25 +553,23 @@ export default {
...
@@ -613,25 +553,23 @@ export default {
file
,
file
,
mode
:
self
.
uploadToken
.
mode
,
mode
:
self
.
uploadToken
.
mode
,
// 七牛才会执行
// 七牛才会执行
percent
(
res
){
percent
(
res
)
{
localMessage
.
percent
=
Math
.
ceil
(
res
.
total
.
percent
);
localMessage
.
percent
=
Math
.
ceil
(
res
.
total
.
percent
);
if
(
res
.
total
.
size
<
1
)
{
if
(
res
.
total
.
size
<
1
)
{
self
.
qiniuObservable
.
unsubscribe
();
self
.
qiniuObservable
.
unsubscribe
();
self
.
cancelMessage
(
localMessage
.
key
);
self
.
cancelMessage
(
localMessage
.
key
);
Toast
({
Toast
({
message
:
"上传失败,该图片已损坏!"
message
:
"上传失败,该图片已损坏!"
});
});
}
}
},
},
success
(
src
){
success
(
src
)
{
uploadSuccess
(
src
);
uploadSuccess
(
src
);
},
},
fail
(){
fail
()
{
uploadError
();
uploadError
();
}
}
});
});
};
};
},
},
// 滚动条置底
// 滚动条置底
...
@@ -745,7 +683,11 @@ export default {
...
@@ -745,7 +683,11 @@ export default {
}
}
var
chatValue
=
this
.
chatValue
.
trim
();
var
chatValue
=
this
.
chatValue
.
trim
();
if
(
chatValue
==
""
)
return
;
if
(
chatValue
==
""
)
return
;
const
message
=
this
.
$mimcInstance
.
sendMessage
(
"text"
,
this
.
account
,
chatValue
);
const
message
=
this
.
$mimcInstance
.
sendMessage
(
"text"
,
this
.
account
,
chatValue
);
message
.
isShowCancel
=
true
;
message
.
isShowCancel
=
true
;
setTimeout
(()
=>
(
message
.
isShowCancel
=
false
),
10000
);
setTimeout
(()
=>
(
message
.
isShowCancel
=
false
),
10000
);
this
.
messagesPushMemory
(
message
);
this
.
messagesPushMemory
(
message
);
...
@@ -754,7 +696,11 @@ export default {
...
@@ -754,7 +696,11 @@ export default {
},
},
// 撤回消息
// 撤回消息
cancelMessage
(
key
)
{
cancelMessage
(
key
)
{
const
message
=
this
.
$mimcInstance
.
sendMessage
(
"cancel"
,
this
.
account
,
key
);
const
message
=
this
.
$mimcInstance
.
sendMessage
(
"cancel"
,
this
.
account
,
key
);
this
.
messagesPushMemory
(
message
);
this
.
messagesPushMemory
(
message
);
this
.
removeMessage
(
this
.
userInfo
.
id
,
key
);
this
.
removeMessage
(
this
.
userInfo
.
id
,
key
);
if
(
this
.
qiniuObservable
)
this
.
qiniuObservable
.
unsubscribe
();
if
(
this
.
qiniuObservable
)
this
.
qiniuObservable
.
unsubscribe
();
...
@@ -762,7 +708,11 @@ export default {
...
@@ -762,7 +708,11 @@ export default {
// 点击知识库消息
// 点击知识库消息
sendKnowledgeMessage
(
content
)
{
sendKnowledgeMessage
(
content
)
{
this
.
handshakeKeywordList
=
[];
this
.
handshakeKeywordList
=
[];
const
message
=
this
.
$mimcInstance
.
sendMessage
(
"text"
,
this
.
account
,
content
);
const
message
=
this
.
$mimcInstance
.
sendMessage
(
"text"
,
this
.
account
,
content
);
this
.
messagesPushMemory
(
message
);
this
.
messagesPushMemory
(
message
);
this
.
chatValue
=
""
;
this
.
chatValue
=
""
;
},
},
...
@@ -793,9 +743,12 @@ export default {
...
@@ -793,9 +743,12 @@ export default {
msg
.
biz_type
==
"pong"
||
msg
.
biz_type
==
"pong"
||
msg
.
biz_type
==
"handshake"
||
msg
.
biz_type
==
"handshake"
||
msg
.
biz_type
==
"into"
msg
.
biz_type
==
"into"
)
)
{
return
;
return
;
this
.
messages
.
push
(
this
.
handlerMessage
(
msg
));
}
var
messages
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
messages
));
messages
.
push
(
this
.
handlerMessage
(
msg
));
this
.
$store
.
commit
(
"updateState"
,
{
messages
});
this
.
scrollIntoBottom
();
this
.
scrollIntoBottom
();
},
},
// 处理头像昵称
// 处理头像昵称
...
@@ -933,7 +886,11 @@ export default {
...
@@ -933,7 +886,11 @@ export default {
}
}
if
(
this
.
searchHandshakeTimer
)
clearTimeout
(
this
.
searchHandshakeTimer
);
if
(
this
.
searchHandshakeTimer
)
clearTimeout
(
this
.
searchHandshakeTimer
);
this
.
searchHandshakeTimer
=
setTimeout
(()
=>
{
this
.
searchHandshakeTimer
=
setTimeout
(()
=>
{
this
.
$mimcInstance
.
sendMessage
(
"search_knowledge"
,
this
.
robotAccount
,
this
.
chatValue
);
this
.
$mimcInstance
.
sendMessage
(
"search_knowledge"
,
this
.
robotAccount
,
this
.
chatValue
);
this
.
searchHandshakeTimer
=
null
;
this
.
searchHandshakeTimer
=
null
;
},
500
);
},
500
);
},
},
...
@@ -1038,21 +995,6 @@ export default {
...
@@ -1038,21 +995,6 @@ export default {
font-size
:
14px
;
font-size
:
14px
;
line-height
:
25px
;
line-height
:
25px
;
}
}
.mini-im-loading
{
display
:
flex
;
width
:
100%
;
position
:
fixed
;
height
100vh
top
:
0
;
left
:
0
;
z-index
:
9
;
right
:
0
;
background-color
:
#fff
!important
;
margin
:
auto
;
align-items
:
center
;
justify-content
:
center
;
}
}
}
.mini-im-container-no-pto
{
.mini-im-container-no-pto
{
...
@@ -1112,14 +1054,14 @@ export default {
...
@@ -1112,14 +1054,14 @@ export default {
&
.expression-btn
{
&
.expression-btn
{
position
:
absolute
;
position
:
absolute
;
left
:
4
5
px
;
left
:
4
0
px
;
top
:
6px
;
top
:
6px
;
z-index
:
99
;
z-index
:
99
;
}
}
&
.workorder-btn
{
&
.workorder-btn
{
position
:
absolute
;
position
:
absolute
;
left
:
70
px
;
left
:
62
px
;
top
:
6px
;
top
:
6px
;
z-index
:
99
;
z-index
:
99
;
width
:
70px
;
width
:
70px
;
...
@@ -1127,9 +1069,13 @@ export default {
...
@@ -1127,9 +1069,13 @@ export default {
font-size
:
14px
;
font-size
:
14px
;
display
:
flex
;
display
:
flex
;
&.show-header
{
left
:
100px
;
}
img
{
img
{
width
:
2
8
px
;
width
:
2
3
px
;
h
ieght
:
28
px
;
h
eight
:
23
px
;
}
}
i
{
i
{
...
@@ -1600,13 +1546,6 @@ export default {
...
@@ -1600,13 +1546,6 @@ export default {
overflow
:
hidden
;
overflow
:
hidden
;
box-shadow
:
1px
1px
8px
2px
#ccc
;
box-shadow
:
1px
1px
8px
2px
#ccc
;
.mini-im-loading,
.mini-im-emoji
{
width
:
360px
!important
;
height
:
500px
!important
;
bottom
:
0
;
margin
:
auto
!important
;
}
.mini-im-emoji
{
.mini-im-emoji
{
box-sizing
:
border-box
;
box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
...
@@ -1718,7 +1657,7 @@ export default {
...
@@ -1718,7 +1657,7 @@ export default {
}
}
span
.expression-btn
{
span
.expression-btn
{
left
:
3
0
px
;
left
:
3
5
px
;
}
}
}
}
}
}
...
...
ui/kefu_client/src/views/workorder.vue
View file @
e3a7f5bd
<
template
>
<
template
>
<div
class=
"container"
>
<div
class=
"container"
>
<mt-header
v-if=
"isShowHeader"
fixed
title=
"工单"
>
<mt-header
v-if=
"isShowHeader"
fixed
title=
"
我的
工单"
>
<div
slot=
"left"
>
<div
slot=
"left"
>
<mt-button
@
click=
"$router.go(-1)"
icon=
"back"
></mt-button>
<mt-button
@
click=
"$router.go(-1)"
icon=
"back"
></mt-button>
</div>
</div>
...
@@ -9,6 +9,26 @@
...
@@ -9,6 +9,26 @@
<span>
创建工单
</span>
<span>
创建工单
</span>
</mt-button>
</mt-button>
</mt-header>
</mt-header>
<div
class=
"list"
:class=
"
{'hide-header': !isShowHeader}">
<div
class=
"no-data"
v-if=
"workorders.lenght
<
=
0
"
>
<img
src=
"../assets/workorder.png"
alt=
""
>
<div>
您还没有发布过工单~
</div>
</div>
<ul
v-else
>
<template
v-for=
"(item,index) in workorders"
>
<li
:key=
"index"
@
click=
"$router.push('/workorder/detail/'+item.id)"
>
<div
class=
"title"
>
{{
item
.
title
}}
</div>
<div>
<span
class=
"type"
>
{{
getTypeName
(
item
.
tid
)
}}
</span>
<span
class=
"date"
>
{{
$formatDate
(
item
.
create_at
)
}}
</span>
</div>
<i
v-if=
"item.status == 1"
style=
"color:#FF9800;"
>
客服已回复
</i>
<i
v-if=
"item.status == 3"
style=
"color:#ccc"
>
工单已结束
</i>
<i
v-if=
"item.status == 0 || item.status == 2"
style=
"color:green"
>
待回复
</i>
</li>
</
template
>
</ul>
</div>
</div>
</div>
</template>
</template>
...
@@ -20,18 +40,89 @@ export default {
...
@@ -20,18 +40,89 @@ export default {
data
()
{
data
()
{
return
{};
return
{};
},
},
created
()
{
document
.
title
=
"我的工单"
},
computed
:
{
computed
:
{
...
mapGetters
([
...
mapGetters
([
'isShowHeader'
'isShowHeader'
,
'workorders'
,
'workorderTypes'
,
])
])
},
},
mounted
()
{},
mounted
()
{
// 获取工单类型
this
.
$store
.
dispatch
(
"onGetWorkorderTypes"
);
// 获取工单列表
this
.
$store
.
dispatch
(
"onGetWorkorders"
);
},
methods
:
{
methods
:
{
getTypeName
(
tid
){
try
{
return
this
.
workorderTypes
.
filter
((
i
)
=>
i
.
id
==
tid
)[
0
].
title
}
catch
(
e
){
console
.
log
(
e
)
return
""
}
}
}
}
};
};
</
script
>
</
script
>
<
style
lang=
"stylus"
scoped
>
<
style
lang=
"stylus"
scoped
>
.no-data
{
text-align
center
padding-top
50px
img{
width
50px
height
50px
}
div
{
color
#666
font-size
12px
}
}
.list
{
padding-top
50px
&.hide-header{
padding-top
0
}
li
{
padding
10px
20px
background
url('../assets/workorder.png')
10px
center
no-repeat
background-size
25px
padding-left
40px
padding-right
70px
border-bottom
1px
solid
#ddd
position
relative
height
40px
.title{
font-size
14px
color
#333
text-overflow
:
ellipsis
;
overflow
:
hidden
;
white-space
:
nowrap
;
}
.type
{
font-size
12px
color
#666
}
.date
{
margin-left
10px
font-size
12px
color
#999
}
i
{
font-style
normal
font-size
11px
position
absolute
right
10px
top
0
height
:
20px
;
bottom
0
margin
auto
0
}
}
}
</
style
>
</
style
>
ui/kefu_client/src/views/workorder_detail.vue
View file @
e3a7f5bd
<
template
>
<
template
>
<div
class=
"container"
>
<div
class=
"container"
>
workorder_detail
<mt-header
v-if=
"isShowHeader"
fixed
:title=
"workorder.title || '工单详情'"
>
<div
slot=
"left"
>
<mt-button
@
click=
"$router.go(-1)"
icon=
"back"
></mt-button>
</div>
<mt-button
slot=
"right"
>
<span>
删除
</span>
</mt-button>
</mt-header>
</div>
</div>
</
template
>
</
template
>
<
script
>
<
script
>
import
{
mapGetters
}
from
'vuex'
import
axios
from
"axios"
;
export
default
{
export
default
{
name
:
"workorder_detail"
,
name
:
"workorder_detail"
,
components
:
{},
components
:
{},
data
()
{
data
()
{
return
{};
return
{
workorder
:
{},
};
},
},
mounted
()
{},
computed
:
{
methods
:
{}
...
mapGetters
([
'isShowHeader'
,
'workorders'
,
'workorderTypes'
,
])
},
created
()
{
document
.
title
=
"工单详情"
const
id
=
this
.
$route
.
params
.
id
this
.
getWorkOrder
(
id
)
},
methods
:
{
getWorkOrder
(
id
){
axios
.
get
(
"/public/workorder/"
+
id
).
then
(
response
=>
{
this
.
workorder
=
response
.
data
.
data
console
.
log
(
this
.
workorder
)
}).
catch
(
error
=>
{
console
.
log
(
error
)
});
}
}
};
};
</
script
>
</
script
>
<
style
lang=
"stylus"
scoped
>
<
style
lang=
"stylus"
scoped
>
...
...
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