64f06602 by zhen

资源监控列表以及详情完成

1 parent 8be3f5e9
......@@ -2,9 +2,4 @@
ENV = 'development'
# base api
# VUE_APP_BASE_API = 'http://192.168.11.94:8081'
# VUE_APP_BASE_API = 'http://192.168.252.25:8081'
VUE_APP_BASE_API = 'https://pre-web-chery.situdata.com'
VUE_APP_WEBRTC_URL = 'pre-jitsi-chery.situdata.com'
# VUE_APP_WEBRTC_URL = 'srtc.situdata.com'
\ No newline at end of file
VUE_APP_BASE_API = 'http://192.168.11.67:8096'
......
# just a flag
VUE_APP_BASE_API = 'https://ft.cheryfs.cn:8100'
VUE_APP_WEBRTC_URL = 'vc.cheryfs.cn:8443'
\ No newline at end of file
......
......@@ -6,12 +6,6 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>云销</title>
<!-- strophe删除待定 -->
<!-- <script src="./libs/strophe/strophe.js"></script>
<script src="./libs/strophe/strophe.disco.min.js?v=1"></script>
<script src="./libs/jquery-2.1.1.min.js"></script>
<script src="./libs/lib-jitsi-meet.min.js"></script> -->
</head>
<body>
<noscript>
......
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
Strophe.addConnectionPlugin("disco",{_connection:null,_identities:[],_features:[],_items:[],init:function(conn){this._connection=conn;this._identities=[];this._features=[];this._items=[];conn.addHandler(this._onDiscoInfo.bind(this),Strophe.NS.DISCO_INFO,"iq","get",null,null);conn.addHandler(this._onDiscoItems.bind(this),Strophe.NS.DISCO_ITEMS,"iq","get",null,null)},addIdentity:function(category,type,name,lang){for(var i=0;i<this._identities.length;i++){if(this._identities[i].category==category&&this._identities[i].type==type&&this._identities[i].name==name&&this._identities[i].lang==lang){return false}}this._identities.push({category:category,type:type,name:name,lang:lang});return true},addFeature:function(var_name){for(var i=0;i<this._features.length;i++){if(this._features[i]==var_name){return false}}this._features.push(var_name);return true},removeFeature:function(var_name){for(var i=0;i<this._features.length;i++){if(this._features[i]===var_name){this._features.splice(i,1);return true}}return false},addItem:function(jid,name,node,call_back){if(node&&!call_back){return false}this._items.push({jid:jid,name:name,node:node,call_back:call_back});return true},info:function(jid,node,success,error,timeout){var attrs={xmlns:Strophe.NS.DISCO_INFO};if(node){attrs.node=node}var info=$iq({from:this._connection.jid,to:jid,type:"get"}).c("query",attrs);this._connection.sendIQ(info,success,error,timeout)},items:function(jid,node,success,error,timeout){var attrs={xmlns:Strophe.NS.DISCO_ITEMS};if(node){attrs.node=node}var items=$iq({from:this._connection.jid,to:jid,type:"get"}).c("query",attrs);this._connection.sendIQ(items,success,error,timeout)},_buildIQResult:function(stanza,query_attrs){var id=stanza.getAttribute("id");var from=stanza.getAttribute("from");var iqresult=$iq({type:"result",id:id});if(from!==null){iqresult.attrs({to:from})}return iqresult.c("query",query_attrs)},_onDiscoInfo:function(stanza){var node=stanza.getElementsByTagName("query")[0].getAttribute("node");var attrs={xmlns:Strophe.NS.DISCO_INFO};if(node){attrs.node=node}var iqresult=this._buildIQResult(stanza,attrs);for(var i=0;i<this._identities.length;i++){var attrs={category:this._identities[i].category,type:this._identities[i].type};if(this._identities[i].name){attrs.name=this._identities[i].name}if(this._identities[i].lang){attrs["xml:lang"]=this._identities[i].lang}iqresult.c("identity",attrs).up()}for(var i=0;i<this._features.length;i++){iqresult.c("feature",{"var":this._features[i]}).up()}this._connection.send(iqresult.tree());return true},_onDiscoItems:function(stanza){var query_attrs={xmlns:Strophe.NS.DISCO_ITEMS};var node=stanza.getElementsByTagName("query")[0].getAttribute("node");if(node){query_attrs.node=node;var items=[];for(var i=0;i<this._items.length;i++){if(this._items[i].node==node){items=this._items[i].call_back(stanza);break}}}else{var items=this._items}var iqresult=this._buildIQResult(stanza,query_attrs);for(var i=0;i<items.length;i++){var attrs={jid:items[i].jid};if(items[i].name){attrs.name=items[i].name}if(items[i].node){attrs.node=items[i].node}iqresult.c("item",attrs).up()}this._connection.send(iqresult.tree());return true}});
\ No newline at end of file
This diff could not be displayed because it is too large.
import request from '@/utils/request'
/**
* 7天业务量
* 资源监控列表
* @param {*} data
*/
export function volumeCalls(data) {
export function getResourceMonitorList(data) {
return request({
url: '/chery/homepage/volumeCalls',
url: '/saleCloud/web/getResourceMonitorList',
method: 'post',
data
})
}
/**
* 通话时长
* 资源监控详情
* @param {*} data
*/
export function durationsCalls(data) {
export function getResourceDetail(data) {
return request({
url: '/chery/homepage/durationsCalls',
url: '/saleCloud/web/getResourceDetail',
method: 'post',
data
})
}
/**
* 资源监控详情修改备注
* @param {*} data
*/
export function saveResourceMonitorRemarks(data) {
return request({
url: '/saleCloud/web/saveResourceMonitorRemarks',
method: 'post',
data
})
......
......@@ -6,7 +6,7 @@ import request from '@/utils/request'
*/
export function login(data) {
return request({
url: '/chery/account/login',
url: '/saleCloud/web/login',
method: 'post',
data
})
......@@ -17,89 +17,7 @@ export function login(data) {
*/
export function logout() {
return request({
url: '/chery/account/logout',
url: '/saleCloud/logout',
method: 'post'
})
}
/**
* 注册
* @param {*} data
*/
export function registry(data) {
return request({
url: '/chery/account/registry',
method: 'post',
data
})
}
/**
* 重置密码
* @param {*} data
*/
export function resetPassword(data) {
return request({
url: '/chery/account/reset-password',
method: 'post',
data
})
}
/**
* 删除
* @param {*} data
*/
export function deleteUser(data) {
return request({
url: '/chery/account/delete',
method: 'post',
data
})
}
/**
* 禁用账号
* @param {*} data
*/
export function accountAvailable(data) {
return request({
url: '/chery/account/available',
method: 'post',
data
})
}
/**
* 账号列表查询
* @param {*} data
*/
export function accountList(data) {
return request({
url: '/chery/account/list',
method: 'post',
data
})
}
/**
* 验证工号是否已存在
* @param {*} data
*/
export function validUsername(data) {
return request({
url: '/chery/account/valid-username',
method: 'post',
data
})
}
/**
* 监控开启关闭
* @param {*} data
*/
export function switchMonitor(data) {
return request({
url: '/chery/account/switch-monitor',
method: 'post',
data
})
}
......
......@@ -43,23 +43,12 @@ export const constantRoutes = [
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
}
]
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
},
{
path: '/',
component: Layout,
redirect: '/monitor',
meta: {
roles: [
PERMISSION_USER_MAP.admin.code,
PERMISSION_USER_MAP.dataAnalyst.code
]
},
meta: {},
children: [
{
path: 'monitor',
......@@ -78,10 +67,17 @@ export const asyncRoutes = [
meta: {
title: '远程订单详情',
icon: 'home'
}
},
props: route => ({ custInfo: route.query })
}
]
},
}
]
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
{
path: '/404',
component: () => import('@/views/404'),
......
......@@ -6,7 +6,7 @@ import permission from './modules/permisssion'
import { login, logout } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { NAME, USER_TYPE, USER_ID, USER_PASS } from '@/utils/mappingData'
import { NAME, ROLE_TYPE, USER_ID, USER_PASS } from '@/utils/mappingData'
Vue.use(Vuex)
......@@ -14,7 +14,7 @@ export default new Vuex.Store({
state: {
token: getToken(),
name: sessionStorage.getItem(NAME),
roles: JSON.parse(sessionStorage.getItem(USER_TYPE)) || '',
roles: JSON.parse(sessionStorage.getItem(ROLE_TYPE)) || '',
userId: sessionStorage.getItem(USER_ID),
resetRouterTemp: '',
userpass: JSON.parse(sessionStorage.getItem(USER_PASS)) || ''
......@@ -34,7 +34,7 @@ export default new Vuex.Store({
},
SET_ROLES: (state, userType) => {
state.roles = userType
sessionStorage.setItem(USER_TYPE, JSON.stringify(userType))
sessionStorage.setItem(ROLE_TYPE, JSON.stringify(userType))
},
SET_ROUTER_TEMP(state, payload) {
state.resetRouterTemp = payload
......@@ -53,9 +53,9 @@ export default new Vuex.Store({
password: password
})
if (res.code === 0) {
commit('SET_ROLES', res.result.roleCode)
commit('SET_ROLES', res.result.role)
commit('SET_NAME', res.result.name)
commit('SET_USER_ID', res.result.username)
commit('SET_USER_ID', res.result.name)
commit('SET_TOKEN', res.result.token)
}
return res
......
// session key
export const NAME = 'name'
export const USER_ID = 'userId'
export const USER_TYPE = 'userType'
export const ROLE_TYPE = 'roleType'
export const USER_PASS = 'userpass'
// 权限字段
......@@ -19,11 +19,3 @@ export const PERMISSION_USER_MAP = {
name: '数据分析员'
}
}
// contactCard const
export const CONTACT_CARD = {
ANSWER_END: 'answerEnd', // 接听挂断
ANSWER: 'answer', // 接听
CALL: 'call', // 呼叫
CALL_END: 'callEnd' // 呼叫挂断
}
......
......@@ -7,7 +7,7 @@ import router from '@/router'
// create an axios instance
const service = axios.create({
// baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
withCredentials: false // send cookies when cross-domain requests
// timeout: 10000 // request timeout
})
......@@ -19,8 +19,7 @@ service.interceptors.request.use(
if (store.state.token) {
// let each request carry token --['X-Token'] as a custom key.
// please modify it according to the actual situation.
config.headers['X-Source'] = 'web'
config.headers['x-auth-token'] = getToken()
config.headers['X-Auth-Token'] = getToken()
}
return config
},
......@@ -45,30 +44,13 @@ service.interceptors.response.use(
*/
response => {
const res = response.data
if (response.config.url.includes('download')) {
if (res && res.code === 0) {
return res
}
if (response.config.url.includes('recognize')) {
return res
}
if (response.config.url.includes('verify')) {
return res
}
// 3703图片未识别 3730报表无数据
if (
(res && res.code === 0) ||
res.code === 2926 ||
res.code === 4001 ||
res.code === 3703 ||
res.code === 3730
) {
return res
} else if (res && res.code === 2909) {
} else if (res && res.code === -1) {
// 2909 登录超时
// cookie失效
Message({
message: res.msg || 'error',
message: res.message || 'error',
type: 'error',
duration: 5 * 1000
})
......@@ -76,7 +58,7 @@ service.interceptors.response.use(
router.push('/login')
} else if (res && res.code) {
Message({
message: res.msg || 'error',
message: res.message || 'error',
type: 'error',
duration: 5 * 1000
})
......
......@@ -24,13 +24,12 @@ export default {
},
methods: {
...mapActions(['login']),
...mapMutations(['SET_ROUTER_TEMP', 'SET_USERPASS']),
...mapMutations(['SET_ROUTER_TEMP']),
async handleLogin({ username, password }) {
try {
this.btnLoading = true
const { code } = await this.login({ username, password })
if (code === 0) {
this.SET_USERPASS(password)
this.$router.push({ path: '/' })
} else {
this.$refs.loginRef.updateCaptcha()
......
......@@ -8,18 +8,18 @@
inline
:model="ruleForm"
>
<el-form-item label="营销员姓名" prop="customName">
<el-form-item label="营销员姓名" prop="username">
<el-input
v-model.trim="ruleForm.customName"
v-model.trim="ruleForm.username"
placeholder="请输入营销员姓名"
maxlength="21"
>
<i slot="prefix" class="el-icon-search"></i
></el-input>
</el-form-item>
<el-form-item label="营销员工号" prop="customId">
<el-form-item label="营销员工号" prop="userId">
<el-input
v-model.trim="ruleForm.customId"
v-model.trim="ruleForm.userId"
placeholder="请输入营销员工号"
maxlength="21"
>
......@@ -39,7 +39,9 @@
</el-form>
</div>
<div class="flex-end mb10">
<el-button type="primary" size="mini" @click="onSubmit">查询</el-button>
<el-button type="primary" size="mini" @click="handleQueryOrderList"
>查询</el-button
>
<el-button size="mini" @click="onReset">重置</el-button>
</div>
<el-table
......@@ -49,34 +51,40 @@
style="width: 100%"
v-loading="loading"
>
<el-table-column align="center" prop="orderId" label="序号" fixed>
<el-table-column
type="index"
label="序号"
fixed
:index="pagination && (pagination.page - 1) * pagination.size + 1"
>
</el-table-column>
<el-table-column
align="center"
prop="createTime"
prop="custName"
label="客户姓名"
width="160"
>
</el-table-column>
<el-table-column
align="center"
prop="callTime"
prop="custTel"
label="客户手机号"
width="160"
>
</el-table-column>
<el-table-column align="center" prop="partnerDesc" label="管理员姓名">
<el-table-column align="center" prop="userName" label="营销员姓名">
</el-table-column>
<el-table-column align="center" prop="customerName" label="营销员工号">
<el-table-column align="center" prop="userId" label="营销员工号">
</el-table-column>
<el-table-column
align="center"
prop="customerPhoneNo"
label="展业时长"
width="160"
>
<el-table-column align="center" label="展业时长" width="160">
<template v-slot="scope">
{{ parseTimeSecond(scope.row.communicationTime * 1000 - 0) }}
</template>
</el-table-column>
<el-table-column align="center" prop="callType" label="展业开始时间">
<el-table-column align="center" label="展业开始时间">
<template v-slot="scope">
{{ parseTime(scope.row.startTime) }}
</template>
</el-table-column>
<el-table-column align="center" label="操作" fixed="right">
<template v-slot="scope">
......@@ -97,7 +105,8 @@
<script>
import FooterPaginationfrom from './components/FooterPagination'
import { parseTime } from '@/utils/util'
import { parseTime, parseTimeSecond } from '@/utils/util'
import { getResourceMonitorList } from '@/api/monitor'
export default {
components: {
......@@ -106,42 +115,53 @@ export default {
data() {
return {
parseTime,
parseTimeSecond,
ruleForm: {
customName: '',
customId: '',
username: '',
userId: '',
times: ''
},
tableData: [{}],
tableData: [],
pagination: null,
loading: false,
total: 0
}
},
methods: {
onSubmit() {
this.$refs.ruleForm.validate(valid => {
if (valid) {
this.handleQueryOrderList()
} else {
return false
}
})
async handleGetResourceMonitorList() {
try {
const {
result: { list, total }
} = await getResourceMonitorList({
username: this.ruleForm.username,
userId: this.ruleForm.userId,
startTime: this.ruleForm.times[0],
endTime: this.ruleForm.times[1],
pageNo: this.pagination.page,
row: this.pagination.size
})
this.tableData = list
this.total = total
} catch (error) {
console.log(error)
}
},
onReset() {
this.ruleForm = {
customName: '',
customId: '',
username: '',
userId: '',
times: ''
}
this.onSubmit()
this.handleQueryOrderList()
},
handleGetPager(data) {
this.pagination = data
// this.onSubmit()
this.handleQueryOrderList()
},
async handleQueryOrderList() {
try {
this.loading = true
await this.handleGetResourceMonitorList()
} catch (error) {
console.log(error)
} finally {
......@@ -151,7 +171,7 @@ export default {
handleDetail(row) {
this.$router.push({
path: 'monitor-details',
query: { id: row.orderId }
query: { ...row }
})
}
}
......
......@@ -3,22 +3,25 @@
<div class="top mb10">
<Card class="info">
<h4 class="mb10">客户信息</h4>
<div class="item">姓名:刘非法</div>
<div class="item">性别:男</div>
<div class="item">证件类型:身份证</div>
<div class="item">证件号:232303199101294123</div>
<div class="item">微信昵称:</div>
<div class="item">状态:交流中</div>
<div class="item">年收入:7万</div>
<div class="item">地址:北京</div>
<div class="item">姓名:{{ custInfoCopy.custName }}</div>
<div class="item">
性别:{{ custInfoCopy.custGender - 0 === 0 ? '女' : '男' }}
</div>
<div class="item">证件类型:{{ custInfoCopy.custIdType }}</div>
<div class="item">证件号:{{ custInfoCopy.custIdNo }}</div>
<div class="item">微信昵称:{{ custInfoCopy.custWxName }}</div>
<div class="item">状态:{{ custInfoCopy.custStatus }}</div>
<div class="item">年收入:{{ custInfoCopy.custIncome }}</div>
<div class="item">地址:{{ custInfoCopy.custAddr }}</div>
<div class="item">备注:{{ custInfoCopy.custRemarks }}</div>
</Card>
<div class="video-wrapper">
<VideoPlayer></VideoPlayer>
<VideoPlayer :url="videoUrl"></VideoPlayer>
</div>
</div>
<Card class="mb10">
<el-form label-width="50px" :model="form">
<el-form-item label="备注">
<el-form label-width="60px" ref="form" :model="form" :rules="rules">
<el-form-item label="备注" prop="remarks">
<el-input
type="textarea"
placeholder="请输入"
......@@ -38,20 +41,75 @@
<script>
import VideoPlayer from '@/components/videoPlayer'
import { getResourceDetail, saveResourceMonitorRemarks } from '@/api/monitor'
export default {
components: {
VideoPlayer
},
props: ['custInfo'],
data() {
return {
form: {
remarks: ''
}
},
rules: {
remarks: [
{ required: true, message: '请输入备注', trigger: 'blur' },
{
min: 1,
max: 200,
message: '长度在 1 到 200 个字符',
trigger: 'blur'
}
]
},
videoUrl: '',
custInfoCopy: this.custInfo
}
},
beforeMount() {
this.handleGetResourceDetail()
},
methods: {
handleSubmit() {}
handleSubmit() {
this.$refs.form.validate(valid => {
if (valid) {
this.handleSaveResourceMonitorRemarks()
}
return false
})
},
async handleGetResourceDetail() {
try {
const {
result: { monitorRemarks, url }
} = await getResourceDetail({
ossId: this.custInfoCopy.ossId,
recordId: this.custInfoCopy.recordId
})
this.form.remarks = monitorRemarks
this.videoUrl = url
} catch (error) {
console.log(error)
}
},
async handleSaveResourceMonitorRemarks() {
try {
const res = await saveResourceMonitorRemarks({
recordId: this.custInfoCopy.recordId,
remarks: this.form.remarks
})
if (res.code === 0) {
this.$message({
message: '更新成功',
type: 'success'
})
}
} catch (error) {
console.log(error)
}
}
}
}
</script>
......
......@@ -26,23 +26,23 @@ module.exports = {
assetsDir: 'static',
// 打包时不生成map文件,减少打包体积,加快打包速度
productionSourceMap: false,
devServer: {
https: true,
inline: true,
proxy: {
'/chery': {
target: process.env.VUE_APP_BASE_API
}
// '/': {
// bypass: devServerProxyBypass,
// secure: false,
// target: serverTarget,
// headers: {
// Host: new URL(serverTarget).host
// }
// }
}
},
// devServer: {
// https: true,
// inline: true,
// proxy: {
// '/chery': {
// target: process.env.VUE_APP_BASE_API
// }
// // '/': {
// // bypass: devServerProxyBypass,
// // secure: false,
// // target: serverTarget,
// // headers: {
// // Host: new URL(serverTarget).host
// // }
// // }
// }
// },
configureWebpack: {},
chainWebpack: config => {
config.resolve.alias
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!