Compare commits

...

2 Commits

Author SHA1 Message Date
doublekou 2c643cb719 新增预测式外呼 10 months ago
doublekou 307a66f94f 新增预测式外呼 10 months ago

@ -2,19 +2,24 @@
# @Description: # @Description:
# @Autor: 飘泊客 # @Autor: 飘泊客
# @Date: 2023-02-13 18:25:04 # @Date: 2023-02-13 18:25:04
# @LastEditors: 飘泊客 # @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
# @LastEditTime: 2023-06-21 15:15:11 # @LastEditTime: 2023-10-10 10:21:00
### ###
ENV = 'development' ENV = 'development'
# 接口地址 http://8.130.96.163:8899 # 接口地址 http://8.130.96.163:8899
VUE_APP_BASE_API = 'https://baiyee.vip' # VUE_APP_BASE_API = 'https://baiyee.vip'
# VUE_APP_BASE_API = 'http://172.18.0.225:8899'//xy #VUE_APP_BASE_API = 'http://172.18.0.225:8899xy'
# # VUE_APP_BASE_API = 'http://172.18.0.228:8899'//ts #VUE_APP_BASE_API = 'http://172.18.0.228:8899ts'
#VUE_APP_BASE_API = 'http://172.18.1.8:8899jt' # jt
# VUE_APP_BASE_API = 'http://8.130.96.163:8899' # VUE_APP_BASE_API = 'http://172.18.1.8:8899'
VUE_APP_BASE_IMG = 'https://baiyee.vip' VUE_APP_BASE_API = 'http://39.100.77.21:8013'
VUE_APP_BASE_IMG = 'http://39.100.77.21:8013'
VUE_APP_WS_API = 'wss://baiyee.vip' VUE_APP_WS_API = 'wss://baiyee.vip'
# 是否启用 babel-plugin-dynamic-import-node插件 # 是否启用 babel-plugin-dynamic-import-node插件
VUE_CLI_BABEL_TRANSPILE_MODULES = true <<<<<<< HEAD
VUE_CLI_BABEL_TRANSPILE_MODULES = true
=======
VUE_CLI_BABEL_TRANSPILE_MODULES = true
>>>>>>> 4025a156f728ac573dc4bae6b4f1f08f2072752c

@ -1124,3 +1124,49 @@ export function getCompensateInfo(params) {
// method: 'post', // method: 'post',
// }) // })
// } // }
// 活动列表-上传excel
export function activityListUploadFiles(data) {
return request({
url: baseObj.url + 'api/act/import',
method: 'post',
data
})
}
// 预测式外呼账号配置
export function addAccount(userName, passWord) {
return request({
url: baseObj.url + '/api/account/conf',
method: 'get',
params: {
userName,
passWord
}
})
}
// 预测式账号查询
export function getAccount() {
return request({
url: baseObj.url + 'api/account/query',
method: 'get'
})
}
// 活动列表-新建活动
export function addActivity(data) {
return request({
url: baseObj.url + 'api/act/add',
method: 'post',
data
})
}
// 活动列表-编辑活动
export function editActivity(data) {
return request({
url: baseObj.url + 'api/act/update',
method: 'post',
data
})
}

@ -53,7 +53,8 @@
</div> </div>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> --> </el-dropdown> -->
<!-- <el-dropdown class="avatar-container right-menu-item hover-effect msg-conent" trigger="hover"> <!-- 消息图标 -->
<!-- <el-dropdown class="avatar-container right-menu-item hover-effect msg-conent" trigger="click">
<el-badge :value="12" :max="99" :hidden="true" class="item"> <el-badge :value="12" :max="99" :hidden="true" class="item">
<div class="msg-icon"><i class="el-icon-message-solid" /></div> <div class="msg-icon"><i class="el-icon-message-solid" /></div>
</el-badge> </el-badge>

@ -32,12 +32,13 @@
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import Logo from './Logo' // import Logo from './Logo'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
import variables from '@/assets/styles/variables.scss' import variables from '@/assets/styles/variables.scss'
export default { export default {
components: { SidebarItem, Logo }, // Logo
components: { SidebarItem },
computed: { computed: {
...mapGetters(['permission_routers', 'sidebar']), ...mapGetters(['permission_routers', 'sidebar']),
activeMenu() { activeMenu() {

@ -136,7 +136,7 @@ import { encrypt } from '@/utils/rsaEncrypt'
import Config from '@/settings' import Config from '@/settings'
import { getCodeImg } from '@/api/login' import { getCodeImg } from '@/api/login'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import { initWebSocket } from '@/utils/websocket' // import { initWebSocket } from '@/utils/websocket'
import agreement from '@/utils/agreement' import agreement from '@/utils/agreement'
// import Background from '@/assets/images/background.jpg' // import Background from '@/assets/images/background.jpg'
import kfcode from '@/assets/images/h5-code.png' import kfcode from '@/assets/images/h5-code.png'

@ -0,0 +1,489 @@
<!--
* @Description: 预测式外呼-活动列表
* @Autor: 飘泊客
* @Date: 2022-01-13 15:43:13
* @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
* @LastEditTime: 2023-10-09 14:30:05
-->
<template>
<div class="app-container">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="用户管理" name="first">
<el-form ref="form" :model="form" :rules="rules" label-position="left" label-width="65px" class="login-form">
<el-form-item prop="userName" label="用户名">
<el-input
v-model="form.userName"
type="text"
auto-complete="off"
placeholder="账号"
>
<svg-icon
slot="prefix"
icon-class="user"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="passWord" label="密码">
<el-input
v-model="form.passWord"
type="password"
auto-complete="off"
placeholder="密码"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="password"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item style="display: flex;justify-content: flex-end;">
<!-- <el-button @click="resetForm('form')"></el-button> -->
<el-button type="primary" :loading="loading" @click="onSubmit('form')"></el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="活动列表" name="second">
<el-row :gutter="20">
<!--工具栏-->
<div class="head-container">
<!-- <div> -->
<!-- 搜索 -->
<!-- <date-range-picker v-model="query.createTime" class="date-item" />
<rrOperation />
</div> -->
<div>
<el-button class="filter-item" size="mini" type="primary" icon="el-icon-plus" @click="add('add')"></el-button>
</div>
</div>
<!--表格渲染-->
<el-table ref="table" v-loading="crud.loading" :data="crud.data" :header-cell-style="{'text-align':'left'}" style="width: 100%;">
<el-table-column :show-overflow-tooltip="true" prop="actName" label="活动名称" />
<!-- <el-table-column :show-overflow-tooltip="true" prop="totalNum" label="总数" /> -->
<el-table-column :show-overflow-tooltip="true" prop="executeTotalNum" label="预执行总数" />
<el-table-column :show-overflow-tooltip="true" prop="executeNum" label="已执行总数" />
<el-table-column :show-overflow-tooltip="true" prop="rateNum" label="接通数" />
<el-table-column :show-overflow-tooltip="true" prop="rate" label="并发数" />
<el-table-column :show-overflow-tooltip="true" prop="status" label="活动状态" />
<el-table-column :show-overflow-tooltip="true" prop="createTime" width="135" label="创建日期">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
width="100"
align="left"
fixed="right"
>
<template slot-scope="scope">
<el-button size="mini" type="text" @click="edit(scope.row,'edit')"></el-button>
<!-- <el-button v-if="scope.row.type === 1 && scope.row.clueNum >= 100" @click="sendEmail(scope.row.id)"></el-button>
<el-button v-if="scope.row.status === 1" type="primary" @click="downloadUrl('email', scope.row)"></el-button>
<el-button v-if="scope.row.type === 2 || (scope.row.type === 1 && scope.row.clueNum < 100)" type="success" @click="downloadUrl('excel', scope.row)">excel</el-button> -->
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<pagination />
</el-row>
<!--新建活动弹出框-->
<el-dialog
append-to-body
:close-on-click-modal="false"
:visible.sync="resourcesDialog"
:before-close="colseFileDialog"
:title="type==='add'?'新建活动':''"
width="520px"
class="import-dialog"
>
<div div class="u-flex">
<div class="label">推送开关</div>
<el-switch
v-model="preTestActDTO.isDmpDelivery"
@change="editTagChange(preTestActDTO.isDmpDelivery)"
/>
</div>
<div div class="u-flex" style="margin-top:18px">
<div class="label">活动名称</div>
<el-input v-model="preTestActDTO.actName" placeholder="请输入活动名称" style="width: 360px" :readonly="type==='edit'" />
</div>
<div v-if="type==='add'" div class="u-flex" style="margin-top:18px">
<div class="label">活动ID</div>
<el-input v-model="preTestActDTO.actId" placeholder="请输入活动ID" style="width: 360px" :readonly="type==='edit'" />
</div>
<div div class="u-flex" style="margin-top:18px">
<div class="label">Tag</div>
<div style="flex-wrap: wrap;">
<el-tag
v-for="tag in preTestActDTO.tagStr"
:key="tag"
closable
:disable-transitions="false"
@close="handleClose(tag)"
>
{{ tag }}
</el-tag>
<el-input
v-if="inputVisible"
ref="saveTagInput"
v-model="inputValue"
class="input-new-tag"
size="small"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
/>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ New Tag</el-button>
</div>
</div>
<!-- <div class="margin-auto">
<el-upload
ref="updaatefiles"
action=""
accept=".xlsx,.xls"
drag
multiple
:limit="5"
class="mt-10 text-center"
style="margin-left: 20px;"
:file-list="fileList"
:auto-upload="false"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:http-request="updtaFils"
>
<i class="el-icon-upload" />
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div slot="tip" class="el-upload__tip">只能上传.xls.xlsx.csv文件且不超过100M</div>
</el-upload>
<div class="line-text margin-auto">
1请导入 xlsxlsx.csv 格式的文件<br>
2必须填写表头方便后续匹配也可点击下载 模板帮助您快速完成导入<br>
3多文件导入请统一提交<br>
4一次最多支持导入 5 份文件<br>
</div>
</div> -->
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="colseFileDialog"></el-button>
<el-button
:loading="uploading"
type="primary"
@click="submitUpload"
>确定</el-button>
</div>
</el-dialog>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import CRUD, { presenter, header, form, crud } from '@crud/crud'
// import rrOperation from '@crud/RR.operation'
import pagination from '@crud/Pagination'
// import DateRangePicker from '@/components/DateRangePicker'
import { sendEmail, addActivity, editActivity } from '@/api/index'
import { mapGetters } from 'vuex'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { addAccount, getAccount } from '@/api/index'
const defaultForm = { }
export default {
name: 'CurrentDownload',
// rrOperation, DateRangePicker
components: { pagination },
cruds() {
return CRUD({ title: '活动列表', url: 'api-management/api/act/query' })
},
mixins: [presenter(), header(), form(defaultForm), crud()],
data() {
return {
height: document.documentElement.clientHeight - 180 + 'px;',
uploading: false,
resourcesDialog: false,
preTestActDTO: {
actId: '', // ID
actName: '', //
isDmpDelivery: true, //
tagStr: [], // tag
taskId: ''
},
inputVisible: false,
inputValue: '',
fileList: [], // files
permission: {
add: ['admin', 'user:add'],
edit: ['admin', 'user:edit'],
del: ['admin', 'user:del'],
download: ['admin', 'user:download']
},
type: '', //
form: {
userName: '',
passWord: ''
// date1: '',
// date2: '',
// delivery: false,
// type: [],
// resource: '',
// desc: ''
},
rules: {
userName: [
{ required: true, trigger: 'blur', message: '用户名不能为空' }
],
passWord: [
{ required: true, trigger: 'blur', message: '密码不能为空' }
],
code: [
{ required: true, trigger: 'change', message: '验证码不能为空' }
]
},
loading: false,
activeName: 'first'// tabs
}
},
computed: {
...mapGetters([
'user'
])
},
created() {},
mounted: function() {
const that = this
window.onresize = function temp() {
that.height = document.documentElement.clientHeight - 180 + 'px;'
}
this.forecastTrialAccountQuery()
},
methods: {
downloadUrl(type, data) {
const a = document.createElement('a')
a.style.display = 'none'
if (type === 'email') {
a.href = data.emailFilePath
}
if (type === 'excel') {
a.href = data.filePath
}
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
},
sendEmail(id) {
sendEmail({ id: id }).then(res => {
this.$message.success('发送成功')
})
},
colseFileDialog() {
this.fileList = []
this.preTestActDTO.actName = ''
this.resourcesDialog = false
},
//
updtaFils(file) {
this.fileData.append('file', file.file)
},
//
handleRemove(file, fileList) {
this.fileList = fileList
},
//
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 5 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
},
submitUpload() {
//
// else if (!isLt100M) {
// this.$message.warning('100MB!')
// }
// const isLt100M = this.fileList.every(file => file.size / 1024 / 1024 < 100)
if (!this.preTestActDTO.actName) {
this.$message.warning('请输入活动名称!')
} else if (!this.preTestActDTO.actId && this.type === 'add') {
this.$message.warning('请输入活动ID!')
} else if (this.preTestActDTO.tagStr.length === 0) {
this.$message.warning('请输入tag!')
} else {
// this.fileData = new FormData() // new formData
// this.$refs['updaatefiles'].submit()
// if (!this.fileData.get('file')) {
// this.$message({
// message: '',
// type: 'warning'
// })
// return false
// }
// this.fileData.append('actName', this.actName)
// this.fileData.append('actId', this.actId)
this.uploading = true
if (this.type === 'add') {
delete this.preTestActDTO.taskId
addActivity(this.preTestActDTO).then((res) => {
// this.$message({
// message: '',
// type: 'success'
// })
// this.fileList = []
// setTimeout(() => {
this.colseFileDialog()
this.crud.toQuery()
this.uploading = false
// }, 3000)
}).catch(() => {
this.uploading = false
})
} else {
delete this.preTestActDTO.actId
editActivity(this.preTestActDTO).then((res) => {
// this.$message({
// message: '',
// type: 'success'
// })
// this.fileList = []
// setTimeout(() => {
this.colseFileDialog()
this.crud.toQuery()
this.uploading = false
// }, 3000)
}).catch(() => {
this.uploading = false
})
}
}
},
//
add(type) {
this.preTestActDTO = {
actId: '', // ID
actName: '', //
isDmpDelivery: true, //
tagStr: []// tag
}
this.resourcesDialog = true
this.type = type
},
//
edit(row, type) {
console.log(row, 'row')
this.preTestActDTO.taskId = row.taskId
this.preTestActDTO.actId = row.actId
this.preTestActDTO.actName = row.actName
this.preTestActDTO.isDmpDelivery = row.isDmpDelivery
this.preTestActDTO.tagStr = row.tagStr
this.resourcesDialog = true
this.type = type
},
onSubmit(form) {
this.$refs[form].validate((valid) => {
if (valid) {
this.loading = true
addAccount(this.form.userName, this.form.passWord).then(res => {
if (res.status === 0) {
this.loading = false
this.$message.success('操作成功')
} else {
this.$message.error(res.msg)
}
}).catch(() => {
this.loading = false
})
} else {
return false
}
})
},
// resetForm(form) {
// this.$refs[form].resetFields()
// },
//
forecastTrialAccountQuery() {
getAccount().then(res => {
if (res.status === 0) {
console.log(res, 'res')
this.form.userName = res.data.dbUserName
this.form.passWord = res.data.dbUserPassword
// this.loading = false
// this.$message.success('')
} else {
this.$message.error(res.msg)
}
}).catch(() => {
// this.loading = false
})
},
// tabs
handleClick(tab, event) {
console.log(tab, event)
},
// change
editTagChange(data) {
data = !data
},
handleClose(tag) {
this.preTestActDTO.tagStr.splice(this.preTestActDTO.tagStr.indexOf(tag), 1)
},
showInput() {
this.inputVisible = true
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus()
})
},
handleInputConfirm() {
const inputValue = this.inputValue
if (inputValue) {
this.preTestActDTO.tagStr.push(inputValue)
}
this.inputVisible = false
this.inputValue = ''
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .vue-treeselect__control,::v-deep .vue-treeselect__placeholder,::v-deep .vue-treeselect__single-value {
height: 30px;
line-height: 30px;
}
.label{
min-width: 70px;
line-height: 32px;
float: none;
display: inline-block;
font-size: 14px;
color: #606266;
text-align: right;
vertical-align: middle;
font-weight: 700;
// padding: 0 20px 0 0;
}
.login-form {
width: 370px;
}
.el-tag + .el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 32px;
line-height: 30px;
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;
vertical-align: bottom;
}
.el-tag--small {
height: 32px;
line-height: 30px;
padding-top: 0;
padding-bottom: 0;
}
</style>

@ -54,7 +54,7 @@ import CRUD, { presenter, header, form, crud } from '@crud/crud'
import rrOperation from '@crud/RR.operation' import rrOperation from '@crud/RR.operation'
import pagination from '@crud/Pagination' import pagination from '@crud/Pagination'
import DateRangePicker from '@/components/DateRangePicker' import DateRangePicker from '@/components/DateRangePicker'
import { sendEmail } from '@/api/index' // import { sendEmail } from '@/api/index'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import '@riophae/vue-treeselect/dist/vue-treeselect.css' import '@riophae/vue-treeselect/dist/vue-treeselect.css'
const defaultForm = { } const defaultForm = { }

Loading…
Cancel
Save