@@ -0,0 +1 @@ | |||
VUE_APP_BASE_API = 'http://192.168.31.160:9999' |
@@ -0,0 +1 @@ | |||
VUE_APP_BASE_API = 'http://39.97.244.65:9999' |
@@ -0,0 +1 @@ | |||
VUE_APP_BASE_API = 'http://127.0.0.1:9999' |
@@ -0,0 +1 @@ | |||
VUE_APP_BASE_API = 'https://www.aihxz.com' |
@@ -0,0 +1 @@ | |||
VUE_APP_BASE_API = 'http://192.168.31.85:9999' |
@@ -5,7 +5,11 @@ | |||
"scripts": { | |||
"pre": "cnpm install || yarn --registry https://registry.npm.taobao.org || npm install --registry https://registry.npm.taobao.org ", | |||
"dev": "vue-cli-service serve", | |||
"cl": "vue-cli-service serve --mode cldevelopment", | |||
"sh": "vue-cli-service serve --mode shdevelopment", | |||
"local": "vue-cli-service serve --mode localdevelopment", | |||
"build": "vue-cli-service build", | |||
"build:test": "vue-cli-service build --mode development", | |||
"build:docker": "vue-cli-service build --dest=./docker/dist/", | |||
"lint": "vue-cli-service lint", | |||
"analyze": "vue-cli-service build --report" | |||
@@ -13,6 +13,7 @@ export default { | |||
computed: {}, | |||
watch: {}, | |||
created() { | |||
console.log(process.env.VUE_APP_BASE_API, 'this is process.env.VUE_APP_BASE_API' + process.env.VUE_APP_BASE_API) | |||
}, | |||
methods: {} | |||
} | |||
@@ -449,6 +449,30 @@ export function updateManagerPhone(data) { | |||
// 无效接待原因数据 | |||
export function invalidList(query) { | |||
return request({ | |||
url: '/autoSR/marketing/invalidList', | |||
method:'get', | |||
params:query | |||
}) | |||
} | |||
// 转写方式数据获取 | |||
export function findTransferMethod(query) { | |||
return request({ | |||
url: '/autoSR/properties/findTransferMethod', | |||
method:'get', | |||
params:query | |||
}) | |||
} | |||
// 确定重新转写 | |||
export function toTransferData(query) { | |||
return request({ | |||
url: '/autoSR/customer/toTransferData', | |||
method:'get', | |||
params:query | |||
}) | |||
} | |||
// 接待记录 | |||
export function findbypage(query) { | |||
return request({ | |||
@@ -1296,4 +1320,49 @@ export function getResultsList(data) { | |||
}) | |||
} | |||
//需求挖掘话术配置-排序提交 | |||
export function updateSort(data) { | |||
return request({ | |||
url: `/autoSR/marketing/updateSort`, | |||
method: 'POST', | |||
data: data | |||
}) | |||
} | |||
//需求挖掘话术配置- 评分保存 | |||
export function saveWordTemplate(data) { | |||
return request({ | |||
url: `/autoSR/zk/keywords/saveWordTemplate`, | |||
method: 'POST', | |||
data: data | |||
}) | |||
} | |||
//需求挖掘话术配置-获取模型数据回显 | |||
export function keymodelfindById(data) { | |||
return request({ | |||
url: `/autoSR/zk/keymodel/findById`, | |||
method: 'GET', | |||
data: data | |||
}) | |||
} | |||
//需求挖掘话术配置-添加问题保存 | |||
export function addQuestion(data) { | |||
return request({ | |||
url: `/autoSR/zk/keywords/addQuestion`, | |||
method: 'POST', | |||
data: data | |||
}) | |||
} | |||
//需求挖掘话术配置-修改保存标签模型 | |||
export function updateKeywordsModel(data) { | |||
return request({ | |||
url: `/autoSR/zk/keymodel/updateKeywordsModel`, | |||
method: 'POST', | |||
data: data | |||
}) | |||
} | |||
@@ -0,0 +1,124 @@ | |||
<template> | |||
<div> | |||
<el-dialog | |||
title="匹配规则" | |||
:visible.sync="value" | |||
append-to-body> | |||
<div style="max-height: 430px;overflow: auto"> | |||
<p> | |||
<b>匹配距离</b>:关键字匹配字数距离,主要针对near/after 生效; | |||
</p> | |||
<p style="padding-left: 15px"> | |||
例如:设置为10,面积 after 140</br> | |||
命中话术:"想买一个面积在140平的"</br> | |||
超出10个字,有关键字不命中话术参考:“房屋面积啊,你们这边有多大的,有没有140平左右的”; | |||
</p> | |||
<p> | |||
<b>or(或)</b>:多个关键词,匹配上1个就行 | |||
</p> | |||
<p style="padding-left: 15px"> | |||
例如标签:自住</br> | |||
匹配模型:自己住 or 给自己</br> | |||
命中话术:我们自己住/给自己买的 | |||
</p> | |||
<p> | |||
<b>and not(非)</b>:排除反面意思 | |||
</p> | |||
<p style="padding-left: 15px"> | |||
例如:北京户口,</br> | |||
匹配模型:是北京户口 and not 不是北京户口</br> | |||
命中话术:我是北京户口;</br> | |||
非面中话术:我不是北京户口 | |||
</p> | |||
<p> | |||
<b>near ( 临近)</b>:1个关键词前后一定范围出现过另一个关键词就算命中,有距离限制 | |||
</p> | |||
<p style="padding-left: 15px"> | |||
例如标签:购房预算 140w</br> | |||
匹配模型:预算 near 140</br> | |||
命中话术:我的预算是140w或大概140w的购房预算 | |||
</p> | |||
<p> | |||
<b>after(后面)</b>:一段文本出现2个关键词,并且按照先后的顺序即算命中,有距离限制 | |||
</p> | |||
<p style="padding-left: 15px"> | |||
例如标签:意向面积 140平</br> | |||
匹配模型: 面积 after 140 ,140在面积后面才算生效;</br> | |||
命中话术:想买一个面积在140平的; | |||
</p> | |||
<!-- <p><b>answer(挖掘话术业务)</b>:顾问执行了挖掘话术,客户回答结果,有距离限制,从客户话术文本开始</p> | |||
<p style="padding-left: 15px">例如标签:北京户口</br> | |||
匹配模型:(w-是 or w-有) and not (w-不是 or w-没有)</br> | |||
命中话术:销售:你有北京户口吗?</br> | |||
客户:有的; | |||
</p> --> | |||
<p> | |||
<b>-n(自定义命中距离)</b>:near/after-n ,单个near/after的匹配距离,n大于0,小于500 | |||
</p> | |||
<p style="padding-left: 15px"> | |||
例如 :面积 after-10 140</br> | |||
10个字内,命中话术参考:"想买一个面积在140平的"</br> | |||
超出10个字,有关键字不命中话术参考:“房屋面积啊,你们这边有多大的,有没有140平左右的”; | |||
</p> | |||
<p> | |||
<b style="color: red;">注意</b>:-n 与 near/after/answer 之间<b style="color: red;">不能有空格</b>; | |||
</p> | |||
<p> | |||
<b>挖掘话术中匹配标签</b>:是针对需求挖掘话术的回答,先选择画像标签,在设置对应的回答结果; | |||
</p> | |||
<p style="padding-left: 15px"> | |||
例如:</br> | |||
挖掘话术:你想买个居室;</br> | |||
标签一:一居 </br> | |||
对应回答:一居or1居or1房or1房 </br> | |||
标签二:两居 </br> | |||
对应回答:2居or两居or2房or两房 </br> | |||
</p> | |||
<p> | |||
<b style="font-weight: bold;">注</b>:优先匹配关键词可以排在前面; | |||
</p> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
data() { | |||
return { | |||
value: false, | |||
}; | |||
}, | |||
props: { | |||
// 控制显示的参数 | |||
innerVisible: { | |||
type: Boolean, | |||
default: false, | |||
}, | |||
}, | |||
created () { | |||
this.value = this.innerVisible | |||
}, | |||
watch: { | |||
innerVisible(newV, oldV) { | |||
console.log(newV, oldV) | |||
this.value = this.innerVisible | |||
} | |||
} | |||
}; | |||
</script> |
@@ -36,11 +36,11 @@ | |||
<div class="text-1">{{ item.agentName }}</div> | |||
<div class="text-2"> | |||
服务状态: | |||
<span | |||
style="font-size: 12px" | |||
:style="item.residueTime > 0 ? 'color:green;' : 'color:red;'" | |||
>{{ item.residueTime > 0 ? "服务中" : "已过期" }}</span | |||
> | |||
<span | |||
style="font-size: 12px" | |||
:style="item.residueTime > 0 ? 'color:green;' : 'color:red;'" | |||
>{{ item.residueTime > 0 ? "服务中" : "已过期" }}</span | |||
> | |||
</div> | |||
<div class="text-3"> | |||
{{ (item.provinceName || "-") + "-" + (item.cityName || "-") }} | |||
@@ -156,7 +156,7 @@ | |||
> | |||
</template> | |||
<template v-else> | |||
<span style="font-size: 12px" :style="'color:red;'">已禁用</span> | |||
<span style="font-size: 12px" :style="'color:red;font-weight: bold;'">已禁用</span> | |||
</template> | |||
</div> | |||
<div class="text-3"> | |||
@@ -38,7 +38,7 @@ | |||
<!-- 项目后台 --> | |||
<!-- 卡片部分 --> | |||
<div class="page-container grid4 xxx"> | |||
<div class="page-container grid5 xxx"> | |||
<div class="nopagechen projectCardItem"> | |||
<div> | |||
<div class="pageboxtitle1">正在接待</div> | |||
@@ -469,6 +469,129 @@ | |||
</div> | |||
</div> | |||
</div> | |||
<div | |||
class="pagechen" | |||
@click=" | |||
toDetail('/ReceivingRecords/index', nowSelectTime(4), '接待记录') | |||
" | |||
> | |||
<div style="width: 100%"> | |||
<div class="pageboxtitle1 projectCardItem"> | |||
<div class="sum"> | |||
<div class="sum-top"> | |||
<div>平均挖掘执行率</div> | |||
<el-tooltip | |||
effect="light" | |||
content="筛选时间内,已标记的有效接待需求挖掘执行的平均值;" | |||
placement="bottom-end" | |||
> | |||
<i class="pop"></i> | |||
</el-tooltip> | |||
</div> | |||
<div class="span1"> | |||
{{ cardlist.datalist.wordFraction || 0 }}% | |||
</div> | |||
</div> | |||
<div class="cardicon"> | |||
<img | |||
src="../../public/img/indexIcon/indexCardIcon11.png" | |||
alt="" | |||
srcset="" | |||
/> | |||
</div> | |||
</div> | |||
<div class="pageboxtitle2 projectColumn"> | |||
<div class="span2"> | |||
<span class="span2-1"> | |||
环比:{{ cardlist.sequential.wordFractionHb || 0 }}</span | |||
> | |||
<span class="span2-2" v-if="cardlist.liftlist.wordFractionHb > 0"> | |||
+{{ cardlist.liftlist.wordFractionHb || 0 }}% | |||
<i class="up"></i> | |||
</span> | |||
<span class="span2-3" v-if="cardlist.liftlist.wordFractionHb < 0"> | |||
{{ cardlist.liftlist.wordFractionHb || 0 }}% | |||
<i class="down"></i> | |||
</span> | |||
<span | |||
style="margin-left: 15px" | |||
v-if="cardlist.liftlist.wordFractionHb > 0" | |||
>数据有所增长</span | |||
> | |||
<span | |||
style="margin-left: 15px" | |||
v-if="cardlist.liftlist.wordFractionHb < 0" | |||
>数据有所下降</span | |||
> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div | |||
class="pagechen" | |||
@click=" | |||
toDetail('/ReceivingRecords/index', nowSelectTime(4), '接待记录') | |||
" | |||
> | |||
<div style="width: 100%"> | |||
<div class="pageboxtitle1 projectCardItem"> | |||
<div class="sum"> | |||
<div class="sum-top"> | |||
<div>平均挖掘成功率</div> | |||
<el-tooltip | |||
effect="light" | |||
content="筛选时间内,已标记的有效接待需求挖掘率成功的平均值;" | |||
placement="bottom-end" | |||
> | |||
<i class="pop"></i> | |||
</el-tooltip> | |||
</div> | |||
<div class="span1"> | |||
{{ cardlist.datalist.wordFinishFraction || 0 }}% | |||
</div> | |||
</div> | |||
<div class="cardicon"> | |||
<img | |||
src="../../public/img/indexIcon/indexCardIcon11.png" | |||
alt="" | |||
srcset="" | |||
/> | |||
</div> | |||
</div> | |||
<div class="pageboxtitle2 projectColumn"> | |||
<div class="span2"> | |||
<span class="span2-1"> | |||
环比:{{ cardlist.sequential.wordFinishFractionHb || 0 }}</span | |||
> | |||
<span class="span2-2" v-if="cardlist.liftlist.wordFinishFractionHb > 0"> | |||
+{{ cardlist.liftlist.wordFinishFractionHb || 0 }}% | |||
<i class="up"></i> | |||
</span> | |||
<span class="span2-3" v-if="cardlist.liftlist.wordFinishFractionHb < 0"> | |||
{{ cardlist.liftlist.wordFinishFractionHb || 0 }}% | |||
<i class="down"></i> | |||
</span> | |||
<span | |||
style="margin-left: 15px" | |||
v-if="cardlist.liftlist.wordFinishFractionHb > 0" | |||
>数据有所增长</span | |||
> | |||
<span | |||
style="margin-left: 15px" | |||
v-if="cardlist.liftlist.wordFinishFractionHb < 0" | |||
>数据有所下降</span | |||
> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="app-box-san"> | |||
@@ -2500,36 +2623,9 @@ export default { | |||
statDateEnd: this.statDateEnd, | |||
}; | |||
this.$api.http.houseIndex(obj).then((res) => { | |||
this.cardlist.datalist = { | |||
receptionCount: res.data.todayStat.receptionCount, | |||
activeCustomer: res.data.todayStat.activeCustomer, | |||
receivingCustomer: res.data.todayStat.receivingCustomer, | |||
avgDuration: res.data.todayStat.avgDuration, | |||
fraction: res.data.todayStat.fraction, | |||
prohibitedCustomer: res.data.todayStat.prohibitedCustomer, | |||
prohibitedZb: res.data.todayStat.prohibitedZb, | |||
accountNum: res.data.todayStat.accountNum, | |||
}; | |||
this.cardlist.liftlist = { | |||
receptionCount: res.data.comparedStat.receptionCount, | |||
activeCustomer: res.data.comparedStat.activeCustomer, | |||
receivingCustomer: res.data.comparedStat.receivingCustomer, | |||
avgDuration: res.data.comparedStat.avgDuration, | |||
fraction: res.data.comparedStat.fraction, | |||
prohibitedCustomer: res.data.comparedStat.prohibitedCustomer, | |||
prohibitedZb: res.data.comparedStat.prohibitedZb, | |||
accountNum: res.data.comparedStat.accountNum, | |||
}; | |||
this.cardlist.sequential = { | |||
receptionCount: res.data.yesterdayStat.receptionCount, | |||
activeCustomer: res.data.yesterdayStat.activeCustomer, | |||
receivingCustomer: res.data.yesterdayStat.receivingCustomer, | |||
avgDuration: res.data.yesterdayStat.avgDuration, | |||
fraction: res.data.yesterdayStat.fraction, | |||
prohibitedCustomer: res.data.yesterdayStat.prohibitedCustomer, | |||
prohibitedZb: res.data.yesterdayStat.prohibitedZb, | |||
accountNum: res.data.yesterdayStat.accountNum, | |||
}; | |||
this.cardlist.datalist = res.data.todayStat | |||
this.cardlist.liftlist = res.data.comparedStat | |||
this.cardlist.sequential = res.data.yesterdayStat | |||
}); | |||
}, | |||
//获取设备 | |||
@@ -2665,6 +2761,13 @@ export default { | |||
grid-row-gap: 18px; | |||
} | |||
.grid5 { | |||
display: grid !important; | |||
grid-template-columns: repeat(5, 20%); | |||
grid-column-gap: 12px; | |||
grid-row-gap: 18px; | |||
} | |||
.page-container { | |||
width: 97%; | |||
display: flex; | |||
@@ -63,6 +63,7 @@ axios.interceptors.response.use(res => { | |||
NProgress.done() | |||
const status = Number(res.status) || 200 | |||
const message = res.data.msg || errorCode[status] || errorCode['default'] | |||
// if (status === 401) { | |||
if (status === 401 || status === 500) { | |||
idx++ | |||
if(idx==1){ | |||
@@ -737,7 +737,7 @@ export default { | |||
this.searchForm.keywordsId = []; | |||
this.searchForm.marketingBusiness = []; | |||
// 获取销讲业务 | |||
this.getMarketingBusiness(); | |||
// this.getMarketingBusiness(); | |||
this.findbypage(); | |||
this.findKeywords(); | |||
// 获取置业顾问列表 | |||
@@ -803,7 +803,7 @@ export default { | |||
this.houseChange(); | |||
// 获取销讲业务 | |||
this.getMarketingBusiness(); | |||
// this.getMarketingBusiness(); | |||
}); | |||
}, | |||
// 置业顾问列表 | |||
@@ -73,28 +73,28 @@ | |||
</span> | |||
<span style="margin-left: 10px"> | |||
<el-button class="editorcd" type="text" size="mini" @click="ddeditor(node, data)">编辑</el-button> | |||
<el-button class="editor" v-if="labelmodelshow" type="text" size="mini" @click="() => moxingEdit(node, data)">编辑模型</el-button> | |||
</span> | |||
<span style="margin-left: 10px"> | |||
<el-button class="remove" type="text" size="mini" @click="remove(node, data)" >删除</el-button> | |||
</span> | |||
</span> | |||
<span v-if="data.level == 3" style="display: flex; align-items: center" > | |||
<span style="margin-left: 10px"> | |||
<span style="margin-left: 10px"> | |||
<el-button class="editorcd" type="text" size="mini" @click="ddeditor(node, data)" >编辑</el-button> | |||
</span> | |||
<span style="margin-left: 10px" v-if="labelmodelshow"> | |||
<el-button class="editorcd" type="text" size="mini" @click="moxingEdit(node, data)" >编辑模型</el-button> | |||
</span> | |||
<span style="margin-left: 10px"> | |||
<el-button class="remove" type="text" size="mini" @click="remove(node, data)" >删除</el-button> | |||
</span> | |||
</span> | |||
</span> | |||
</el-tree> | |||
</div> | |||
<el-dialog title="新增" :visible.sync="dialogFormVisible" :center="true" width="400px"> | |||
<el-dialog title="新增" :visible.sync="dialogFormVisible" :center="true" width="600px"> | |||
<div | |||
v-if="amountintervalname == '意向面积'" | |||
style="display: flex; height: 40px; line-height: 40px" | |||
@@ -149,6 +149,18 @@ | |||
> | |||
<el-input v-model="addForm.name" placeholder="三级名称" maxlength="8" autocomplete="off"></el-input> | |||
</el-form-item> | |||
<el-form-item label="场景描述:" :label-width="formLabelWidth" v-if="level==2||level==3"> | |||
<el-input | |||
type="textarea" | |||
maxlength="100" | |||
show-word-limit | |||
:autosize="{ minRows: 4, maxRows: 8}" | |||
placeholder="请输入内容" | |||
v-model="addForm.sceneDesc"> | |||
</el-input> | |||
<div>增加场景描述有利于标签命中,场景越丰富触达越精准; | |||
例如:意向面积:120平,场景:我想要一个120平的;</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
@@ -166,10 +178,8 @@ | |||
</span> | |||
</el-dialog> | |||
<!--?编辑弹框?--> | |||
<el-dialog title="编辑" :visible.sync="isshowage" :center="true" width="400px"> | |||
<el-dialog title="编辑" :visible.sync="isshowage" :center="true" width="600px"> | |||
<div | |||
v-if="amountintervalname == '意向面积'" | |||
style="display: flex; height: 40px; line-height: 40px" | |||
@@ -200,19 +210,33 @@ | |||
></span> | |||
<span style="margin-left: 6px">万元</span> | |||
</div> | |||
<div v-else style="display: flex; align-items: center; height: 40px"> | |||
<div style="height: 30px; line-height: 30px"> | |||
类名: | |||
<div v-else style="display: flex;align-items: center;height: 40px;"> | |||
<div style="width:90px"> | |||
类名: | |||
</div> | |||
<div style="width:88%"> | |||
<el-input maxlength="8" | |||
v-model="frosasd.name" | |||
placeholder="类名" | |||
type="text" | |||
></el-input> | |||
</div> | |||
<div style="display: flex; align-items: center;margin-top:20px" v-if="frosasd.level==2||frosasd.level==3"> | |||
<div style="width:105px"> | |||
场景描述: | |||
</div> | |||
<div> | |||
<el-input | |||
type="textarea" | |||
maxlength="100" | |||
show-word-limit | |||
:autosize="{ minRows: 4, maxRows: 8}" | |||
placeholder="请输入内容" | |||
v-model="frosasd.desc"> | |||
</el-input> | |||
<div>增加场景描述有利于标签命中,场景越丰富触达越精准; | |||
例如:意向面积:120平,场景:我想要一个120平的;</div> | |||
</div> | |||
</div> | |||
<div style="display: flex; justify-content: center; margin-top: 40px"> | |||
<button | |||
style=" | |||
@@ -249,13 +273,21 @@ | |||
<el-dialog title="新增一级" :visible.sync="dialogVisible2" :center="true" width="400px"> | |||
<el-form :model="addForm2"> | |||
<el-row :gutter="24"> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="名称:" | |||
> | |||
<el-input style="width:300px;" placeholder="名称" v-model="addForm2.name" maxlength="8" autocomplete="off"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-form-item | |||
label="是否必选:" | |||
> | |||
<el-radio-group v-model="addForm2.mustSelected"> | |||
<el-radio :label="0">是</el-radio> | |||
<el-radio :label="1">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-row> | |||
</el-form> | |||
<span slot="footer" class="dialog-footer" style="border-top:1px solid #eee;padding-top: 20px;display: flex;justify-content: end;"> | |||
@@ -263,7 +295,87 @@ | |||
<el-button type="primary" @click="addclick()">确 定</el-button> | |||
</span> | |||
</el-dialog> | |||
<!-- 匹配模型 --> | |||
<el-dialog | |||
title="编辑模型" | |||
@open="openModel" | |||
:close-on-click-modal="false" | |||
:visible.sync="moxingVisible" | |||
> | |||
<el-dialog | |||
title="匹配规则" | |||
:visible.sync="innerVisible" | |||
append-to-body> | |||
<div style="max-height: 430px;overflow: auto"> | |||
<p><b>匹配距离</b>:关键字匹配字数距离,主要针对near/after/w- 生效,w- 的字数统计从挖掘话术后,客户的第一句话开始统计;</p> | |||
<p style="padding-left: 15px">例如:设置为10,面积 after 140</br> | |||
命中话术:"想买一个面积在140平的"</br> | |||
超出10个字,有关键字不命中话术参考:“房屋面积啊,你们这边有多大的,有没有140平左右的”;</p> | |||
<p><b>or(或)</b>:多个关键词,匹配上1个就行</p> | |||
<p style="padding-left: 15px">例如标签:自住</br> | |||
匹配模型:自己住 or 给自己</br> | |||
命中话术:我们自己住/给自己买的</p> | |||
<p><b>and not(非)</b>:排除反面意思</p> | |||
<p style="padding-left: 15px">例如:北京户口,</br> | |||
匹配模型:是北京户口 and not 不是北京户口</br> | |||
命中话术:我是北京户口;</br> | |||
反面话术:我不是北京户口</p> | |||
<p><b>near ( 临近)</b>:1个关键词前后一定范围出现过另一个关键词就算命中,有距离限制</p> | |||
<p style="padding-left: 15px">例如标签:购房预算 140w</br> | |||
匹配模型:预算 near 140</br> | |||
命中话术:我的预算是140w或大概140w的购房预算</p> | |||
<p><b>after(后面)</b>:一段文本出现2个关键词,并且按照先后的顺序即算命中,有距离限制</p> | |||
<p style="padding-left: 15px">例如标签:意向面积 140平</br> | |||
匹配模型: 面积 after 140 ,140在面积后面才算生效;</br> | |||
命中话术:想买一个面积在140平的;</p> | |||
<p><b>w-(挖掘话术业务)</b>:顾问执行了挖掘话术,客户回答结果,有距离限制,从客户话术文本开始</p> | |||
<p style="padding-left: 15px">例如标签:北京户口</br> | |||
匹配模型:(w-是 or w-有) and not (w-不是 or w-没有) | |||
命中话术:销售:你有北京户口吗?</br> | |||
客户:有的;</p> | |||
<p><b>-n(命中距离)</b>:near/after-n ,单个near/after的匹配距离,n大于0,小于500</p> | |||
<p style="padding-left: 15px">例如 :面积 after-10 140</br> | |||
10个字内,命中话术参考:"想买一个面积在140平的"</br> | |||
超出10个字,有关键字不命中话术参考:“房屋面积啊,你们这边有多大的,有没有140平左右的”;</p> | |||
<p><b>注意</b>:-n 与 near/after/answer 之间<b>不能有空格</b>;</p></br> | |||
<p><b>注意</b>:优先匹配关键词可以排在前面;</p> | |||
</div> | |||
</el-dialog> | |||
<el-form ref="form" size="mini" :inline="true" :model="form" label-position="right"> | |||
<el-form-item label="标签名称:"> | |||
<div style="max-width:400px;min-width: 200px;font-weight: bold">{{form.keywordsName}}</div> | |||
</el-form-item> | |||
<el-form-item label="场景描述:"> | |||
<div v-if="form.sceneDesc" style="width:500px;border: 1px dashed #ccc;padding:5px 10px;line-height: 25px"> {{form.sceneDesc}}</div> | |||
<div v-else>暂无描述</div> | |||
</el-form-item> | |||
<el-form-item label="after,near,w- 匹配距离:"> | |||
<el-input-number v-model="form.distance" controls-position="right" :min="0" :max="500"></el-input-number></el-input><span style="color:red;margin-left:10px">*请输入0~500内的整数</span> <el-button type="text" style="margin-left:30px" @click="innerVisible=true">规则说明</el-button> | |||
</el-form-item> | |||
<div contentEditable="true" | |||
@click="myeditorenter($event)" | |||
@keypress.enter="myeditorenter($event)" | |||
@blur="saveRange" | |||
class="editDiv" | |||
id="huashuModel"> | |||
</div> | |||
<div v-if="dynamiclist.length">需求挖掘匹配:</div> | |||
<div class="dynamicbox"> | |||
<div v-for="item in dynamiclist" :key="item" class="itemlist"> | |||
<el-input size="small" disabled style="width: 220px" v-model="item.question"></el-input> | |||
<div class="item-input" style="pointer-events: none;" v-html="item.editValue"></div> | |||
</div> | |||
</div> | |||
<el-form-item label="插入节点:"> | |||
<el-button size="mini" type="primary" style="margin-left:8px;" v-for="(item,index) in taglist" :key="index" @click="insertTag(item,index)">{{item.label}}</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<span slot="footer" class="dialog-footer"> | |||
<el-button @click="moxingVisible = false">取 消</el-button> | |||
<el-button type="primary" @click="saveFun">保 存</el-button> | |||
</span> | |||
</el-dialog> | |||
</div> | |||
</div> | |||
@@ -274,6 +386,39 @@ import { mapGetters } from "vuex"; | |||
export default { | |||
data() { | |||
return { | |||
dynamiclist: [], | |||
taglist:[ | |||
{ | |||
label: 'or (或)', | |||
value: 'or' | |||
}, | |||
{ | |||
label: 'near (临近)', | |||
value: 'near' | |||
}, | |||
{ | |||
label: 'after (后面)', | |||
value: 'after' | |||
}, | |||
{ | |||
label: 'and not (非)', | |||
value: 'and not' | |||
}, | |||
// { | |||
// label: '~ (至)', | |||
// value: '~' | |||
// }, | |||
], | |||
moxingVisible: false, | |||
innerVisible: false, | |||
form: { | |||
keywordsName: '', | |||
id: '', | |||
keywordsId: '', | |||
distance: 10, | |||
sceneDesc:'', | |||
originalExpression: '' | |||
}, | |||
formLabelWidth: "120px", | |||
dialogFormVisible: false, | |||
dialogVisible: false, | |||
@@ -287,9 +432,11 @@ export default { | |||
addForm: { | |||
name: "", | |||
endName: "", | |||
sceneDesc: '' | |||
}, | |||
addForm2:{ | |||
name:'' | |||
name:'', | |||
mustSelected:0 | |||
}, | |||
level: 0, | |||
pid: "", | |||
@@ -303,6 +450,7 @@ export default { | |||
orgCode: "", | |||
sort: "", | |||
level: "", | |||
desc: '' | |||
}, | |||
amountintervalname: "", | |||
isInterval: "", | |||
@@ -314,12 +462,228 @@ export default { | |||
}, | |||
created() { | |||
this.yyc_add_level1 = this.permissions["yyc_add_level1"]; | |||
this.labelmodelshow = this.permissions["labelmodelshow"]; // 编辑模型按钮权限 | |||
}, | |||
mounted() { | |||
// 获取项目列表 | |||
this.zkhousePage(); | |||
}, | |||
methods: { | |||
// 基于保存的光标插入内容 --用于失去焦点后再继续插入内容 | |||
insertContent(str) { | |||
let selection, range = window._range;// 当前光标位置对象 | |||
if (!window.getSelection) { | |||
range.pasteHTML(str); | |||
range.collapse(false); | |||
range.select(); | |||
} else { | |||
selection = window.getSelection ? window.getSelection() : document.selection; | |||
range.collapse(false); | |||
let hasR = range.createContextualFragment(str); | |||
let hasR_lastChild = hasR.lastChild; | |||
while (hasR_lastChild && hasR_lastChild.nodeName.toLowerCase() == "br" && hasR_lastChild.previousSibling && hasR_lastChild.previousSibling.nodeName.toLowerCase() == "br") { | |||
let e = hasR_lastChild; | |||
hasR_lastChild = hasR_lastChild.previousSibling; | |||
hasR.removeChild(e); | |||
} | |||
range.insertNode(hasR); | |||
if (hasR_lastChild) { | |||
range.setEndAfter(hasR_lastChild); | |||
range.setStartAfter(hasR_lastChild); | |||
} | |||
selection.removeAllRanges(); | |||
selection.addRange(range); | |||
} | |||
}, | |||
// 失去焦点时保存光标位置 | |||
saveRange: () => { | |||
let selection = window.getSelection ? window.getSelection() : document.selection; | |||
if (!selection.rangeCount) return; | |||
let range = selection.createRange ? selection.createRange() : selection.getRangeAt(0); | |||
window._range = range; | |||
}, | |||
// 回显模型数据,Dialog 的内容是懒渲染的,即在第一次被打开之前,传入的默认 slot 不会被渲染到 DOM 上,so在 open 事件回调中进行 | |||
openModel(){ | |||
// this.$nextTick(()=>{ | |||
// let huashuModel = document.getElementById('huashuModel') | |||
// huashuModel.innerHTML = this.form.originalExpression | |||
// }) | |||
}, | |||
//格式化粘贴文本方法 | |||
onPaste(event) { | |||
var e = event || window.event | |||
// 阻止默认粘贴 | |||
e.preventDefault(); | |||
// 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
// clipboardData的getData(fomat) 从剪贴板获取指定格式的数据 | |||
var text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('在这里输入文本'); | |||
//清除回车 | |||
text = text.replace(/\[\d+\]|\n|\r/ig,"") | |||
// 插入 | |||
document.execCommand("insertText", false, text); | |||
}, | |||
myeditorenter(e) { | |||
e.preventDefault(); | |||
}, | |||
// 插入节点 | |||
insertHtmlAtCaret(html) { | |||
document.getElementById('huashuModel').focus(); | |||
var sel, range; | |||
if (window.getSelection) { | |||
// IE9 and non-IE | |||
sel = window.getSelection(); | |||
if (sel.getRangeAt && sel.rangeCount) { | |||
range = sel.getRangeAt(0); | |||
range.deleteContents(); | |||
// Range.createContextualFragment() would be useful here but is | |||
// non-standard and not supported in all browsers (IE9, for one) | |||
var el = document.createElement("div"); | |||
el.innerHTML = html; | |||
var frag = document.createDocumentFragment(), | |||
node, lastNode; | |||
while ((node = el.firstChild)) { | |||
lastNode = frag.appendChild(node); | |||
} | |||
range.insertNode(frag); | |||
// Preserve the selection | |||
if (lastNode) { | |||
range = range.cloneRange(); | |||
range.setStartAfter(lastNode); | |||
range.collapse(true); | |||
sel.removeAllRanges(); | |||
sel.addRange(range); | |||
} | |||
} | |||
} else if (document.selection && document.selection.type != "Control") { | |||
// IE < 9 | |||
document.selection.createRange().pasteHTML(html); | |||
} | |||
}, | |||
// 点击插入标签 | |||
insertTag(item,index){ | |||
if(window._range){ | |||
this.insertContent("<span contentEditable='false' style='color:red'>"+item.value+"</span><text> </text>"); | |||
}else{ | |||
this.insertHtmlAtCaret("<span contentEditable='false' style='color:red'>"+item.value+"</span><text> </text>"); | |||
} | |||
}, | |||
// 处理标签,删除不需要的标签格式 | |||
delMark(str) { | |||
const hasStr = (str) => { | |||
let index = str.indexOf('<') | |||
let index1 = str.indexOf('>') | |||
if(index>0&&index1>0){ | |||
let replaceStr= str.substring(index, index1+1) | |||
str= str.replace(replaceStr,'') | |||
hasStr(str) | |||
} | |||
} | |||
hasStr(str) | |||
}, | |||
// 处理模型 关键词加#号 | |||
replaceFun(str){ | |||
let temp = str | |||
temp = temp.replace(/<text>\ \;<\/text>/g,''); | |||
temp = temp.replace(/\ \;/g,''); | |||
temp = temp.replace(/<text>/g,''); | |||
temp = temp.replace(/<\/text>/g,''); | |||
temp = temp.replace(/<span contenteditable="false" style="color:red">/g,' #');// 后台返回是这样的,变了,需要也处理一下 | |||
temp = temp.replace(/<span style="color:red" contenteditable="false">/g,' #'); | |||
temp = temp.replace(/<\/span>/g,'#') | |||
// console.log(temp); | |||
this.delMark(temp); | |||
return temp | |||
}, | |||
// 模型保存 | |||
saveFun(){ | |||
let text = document.getElementById('huashuModel'); | |||
// console.log(text.innerHTML); | |||
// console.log(text.innerText); | |||
let temp = text.innerHTML | |||
if(this.form.distance=='') {this.$message.error('请输入距离'); return;} | |||
if(text.innerText=='') {this.$message.error('请输入标签模型'); return;} | |||
axios({ | |||
url: `/autoSR/zk/keymodel/updateKeywordsModel`, | |||
method: 'post', | |||
data: { | |||
id: this.form.id, | |||
houseId: this.houseId, | |||
level: this.level, | |||
keywordsId: this.form.keywordsId, | |||
keywordsName: this.form.keywordsName, | |||
answerList: [], | |||
keyType: 2, | |||
formatExpression: this.replaceFun(temp),// 问题表达式 | |||
original: temp,// html数据 | |||
showFormatExpression: text.innerText, | |||
distance: this.form.distance // * 距离 | |||
} | |||
}).then(data => { | |||
this.moxingVisible = false | |||
if(data.code==0){ | |||
this.$message.success(data.data) | |||
this.getorgCode() | |||
}else{ | |||
this.$message.error(data.msg) | |||
} | |||
}).catch((e)=>{ | |||
this.moxingVisible = false | |||
}) | |||
}, | |||
moxingEdit(node, data){ | |||
this.level = data.level | |||
this.form.keywordsName = data.endName?data.name+'~'+data.endName:data.name | |||
this.form.keywordsId = data.keywordsId | |||
this.form.sceneDesc = data.desc ||'' | |||
// 获取模型数据回显 | |||
axios({ | |||
url: `/autoSR/zk/keymodel/findById`, | |||
method: 'get', | |||
params: { | |||
houseId: this.houseId, | |||
level: this.level, | |||
keyType: 2, | |||
keywordsId: data.id | |||
} | |||
}).then(res => { | |||
// console.log(res) | |||
this.moxingVisible = true | |||
if (res.code == 0) { | |||
let obj = res.data | |||
if(obj!=null){ | |||
this.form.distance=obj.distance||10 | |||
this.form.originalExpression= obj.originalExpression | |||
this.form.id =obj.id | |||
// 回显标签模型数据 | |||
if(obj.answerList&&obj.answerList.length){ | |||
this.dynamiclist = obj.answerList.map(cont=>{ | |||
return { | |||
question: cont.question, | |||
editValue: cont.originalExpression | |||
} | |||
}) | |||
// console.log(this.dynamiclist) | |||
}else{ | |||
this.dynamiclist = [] | |||
} | |||
}else{ | |||
this.form.distance=10 | |||
this.form.originalExpression= this.form.keywordsName | |||
this.form.id ='' | |||
} | |||
}else{ | |||
this.form.distance = 10 | |||
this.form.originalExpression = this.form.keywordsName | |||
} | |||
this.$nextTick(()=>{ | |||
let huashuModel = document.getElementById('huashuModel') | |||
huashuModel.innerHTML = this.form.originalExpression | |||
}) | |||
}).catch((e)=>{ | |||
this.moxingVisible = true | |||
}) | |||
}, | |||
addclick(){ | |||
var orgCode=''; | |||
if(localStorage.getItem("orgType") == 3){ | |||
@@ -334,12 +698,21 @@ export default { | |||
data: { | |||
pid: 0, | |||
name: this.addForm2.name, | |||
mustSelected: this.addForm2.mustSelected, | |||
level:1, | |||
orgCode:orgCode, | |||
houseId:this.houseId | |||
}, | |||
}).then((res) => { | |||
this.dialogVisible2=false; | |||
if(res.code ==0){ | |||
this.dialogVisible2=false; | |||
this.getHouse() | |||
}else{ | |||
this.$message({ | |||
message: res.msg||'添加失败', | |||
type: "error", | |||
}); | |||
} | |||
}) | |||
}else{ | |||
this.$message({ | |||
@@ -363,7 +736,7 @@ export default { | |||
}, | |||
}).then((res) => { | |||
if (res.code == 0) { | |||
console.log(res.data); | |||
// console.log(res.data); | |||
this.treeList = res.data; | |||
} | |||
}); | |||
@@ -373,6 +746,7 @@ export default { | |||
this.amountintervalname = data.name; | |||
this.addForm.name = ""; | |||
this.addForm.endName = ""; | |||
this.addForm.sceneDesc = ''; | |||
this.pid = data.id; | |||
this.level = data.level + 1; | |||
this.orgCode = data.orgCode; | |||
@@ -436,6 +810,8 @@ export default { | |||
level: this.level, | |||
orgCode: this.orgCode, | |||
isInterval: this.isInterval, | |||
houseId:this.houseId, | |||
desc:this.addForm.sceneDesc, | |||
}, | |||
}).then((res) => { | |||
if (res.code == 0) { | |||
@@ -474,18 +850,18 @@ export default { | |||
}); | |||
}); | |||
} | |||
this.zkhousePage() | |||
} | |||
}); | |||
}, | |||
//删除节点 | |||
remove(node, data) { | |||
// console.log(data, "123"); | |||
this.deleteId = data.id; | |||
if (data.level == 3) { | |||
this.deleteId = data.id; | |||
this.dialogVisible = true; | |||
} else { | |||
if (data.children.length == 0) { | |||
this.deleteId = data.id; | |||
this.dialogVisible = true; | |||
} else { | |||
this.$message({ | |||
@@ -502,6 +878,7 @@ export default { | |||
method: "get", | |||
params: { | |||
id: this.deleteId, | |||
houseId:this.houseId | |||
}, | |||
}).then((res) => { | |||
if (res.code == 0) { | |||
@@ -534,6 +911,7 @@ export default { | |||
orgCode: "", | |||
sort: "", | |||
level: "", | |||
desc: '' | |||
}; | |||
if (data.isInterval == 0) { | |||
this.frosasd.isInterval = 0; | |||
@@ -554,6 +932,7 @@ export default { | |||
this.frosasd.orgCode = data.orgCode; | |||
this.frosasd.sort = data.sort; | |||
this.frosasd.level = data.level; | |||
this.frosasd.desc = data.desc; | |||
this.isshowage = true; | |||
}, | |||
//取消编辑 | |||
@@ -600,12 +979,11 @@ export default { | |||
axios({ | |||
url: `/autoSR/zk/keywords/update`, | |||
method: "post", | |||
data: this.frosasd, | |||
data: {...this.frosasd,houseId: this.houseId}, | |||
}).then((res) => { | |||
if (res.code == 0) { | |||
this.getHouse() | |||
that.isshowage=false; | |||
return | |||
that.treeList.forEach((item, index) => { | |||
item.children.forEach((asd, indexesd) => { | |||
if (asd.id == that.frosasd.id) { | |||
@@ -656,6 +1034,17 @@ export default { | |||
/deep/.el-tree-node__content{ | |||
overflow: hidden; | |||
} | |||
.editDiv{ | |||
width:100%; | |||
min-height:60px; | |||
max-height:120px; | |||
overflow:auto; | |||
margin-bottom:10px; | |||
padding: 15px; | |||
outline: none; | |||
border:1px solid #409EFF; | |||
border-radius: 10px; | |||
} | |||
.box-center { | |||
width: 100%; | |||
padding: 15px 15px 20px; | |||
@@ -763,4 +1152,24 @@ overflow: hidden; | |||
/deep/ .el-button--text{ | |||
color: #2671E2; | |||
} | |||
.itemlist { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
margin: 20px 0; | |||
} | |||
.item-input { | |||
width: 100%; | |||
padding: 4px 10px; | |||
outline: none; | |||
border: 1px solid #409eff; | |||
border-radius: 4px; | |||
overflow: auto; | |||
line-height: 24px; | |||
min-height: 24px; | |||
max-height: 100px; | |||
margin: 0 10px; | |||
} | |||
</style> |
@@ -29,7 +29,7 @@ | |||
> | |||
<div v-if="rec_index_addJ" @click="Addtodigest()"> | |||
<div | |||
v-if="arr[this.aplayerId].status == 0" | |||
v-if="arr[aplayerId].status == 0" | |||
style="display: flex; align-items: center" | |||
> | |||
<i class="el-icon-star-on" style="font-size: 20px"></i> | |||
@@ -297,18 +297,46 @@ | |||
</span> | |||
{{ item.bg | timestamp }} | |||
</div> | |||
<div class="textcontent"> | |||
<div | |||
class="content123s" | |||
:class="{ adjskdjroleindexclass: item.isShow == 1 }" | |||
v-html="item.onebest" | |||
></div> | |||
<img | |||
@click.stop="play(item)" | |||
src="./icon/play.png" | |||
alt="" | |||
style="flex-shrink: 0; width: 24px; height: 24px" | |||
/> | |||
<div class="textcontent1"> | |||
<div class="textcontent"> | |||
<div | |||
class="content123s" | |||
:class="{ adjskdjroleindexclass: item.isShow == 1 }" | |||
v-html="item.onebest" | |||
></div> | |||
<img | |||
@click.stop="play(item)" | |||
src="./icon/play.png" | |||
alt="" | |||
style="flex-shrink: 0; width: 24px; height: 24px" | |||
/> | |||
</div> | |||
<!-- 1 客户画像 2销讲词 3违禁 4 需求挖掘 --> | |||
<div class="showmark" v-if="item.types"> | |||
<div> | |||
<div | |||
class="mark-item" | |||
v-for="(subitem, i) in dealTypes(item.types)" | |||
:key="i" | |||
> | |||
<img | |||
v-if="dealword(subitem)[0]" | |||
class="markicon" | |||
:src="imgArr[dealword(subitem)[0]]" | |||
/> | |||
<p | |||
class="marktext" | |||
:style=" | |||
dealword(subitem)[0] == 3 | |||
? 'color:#E7483C' | |||
: 'color:#3E50E8' | |||
" | |||
> | |||
{{ dealword(subitem)[1] }} | |||
</p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -463,79 +491,38 @@ | |||
height: 100px; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
border-bottom: 1px solid #e0e0e0; | |||
" | |||
> | |||
<div | |||
style=" | |||
width: 100%; | |||
height: 44px; | |||
display: flex; | |||
align-items: center; | |||
margin: 10px 0 20px; | |||
font-size: 16px; | |||
color: #333333; | |||
text-indent: 5%; | |||
" | |||
> | |||
<div | |||
style="flex: 1; font-size: 16px; color: #333333; text-indent: 5%" | |||
> | |||
销讲执行 | |||
</div> | |||
销讲执行 | |||
</div> | |||
<div class="pingfenbox"> | |||
<el-button | |||
:class="{ activecllasscet: zhixingcenterindex == 0 }" | |||
type="" | |||
style=" | |||
height: 32px; | |||
border-right: none; | |||
border-radius: 5px 0 0 5px; | |||
" | |||
@click="recordclick(0)" | |||
>销讲总执行率{{ userinformationlist.fraction || 0 }}%</el-button | |||
<el-radio-group v-model="zhixingcenterindex" size="small"> | |||
<el-radio-button :label="0" | |||
>销讲总执行率{{ | |||
userinformationlist.fraction || 0 | |||
}}%</el-radio-button | |||
> | |||
<el-button | |||
:class="{ activecllasscet: zhixingcenterindex == 1 }" | |||
type="" | |||
style=" | |||
margin-left: 0px; | |||
height: 32px; | |||
width: 126.5px; | |||
border-left: none; | |||
border-radius: 0 5px 5px 0; | |||
" | |||
@click="recordclick(1)" | |||
>禁忌执行</el-button | |||
> | |||
</div> | |||
<el-radio-button :label="1">禁忌执行</el-radio-button> | |||
<el-radio-button :label="2">需求挖掘率</el-radio-button> | |||
</el-radio-group> | |||
</div> | |||
<div v-if="zhixingcenterindex == 0"> | |||
<div | |||
style=" | |||
width: 100%; | |||
height: 44px; | |||
border-bottom: 1px solid #e0e0e0; | |||
display: flex; | |||
align-items: center; | |||
background: #f0f6ff; | |||
" | |||
> | |||
<div | |||
style=" | |||
width: 60%; | |||
font-size: 16px; | |||
color: #333333; | |||
text-indent: 20px; | |||
" | |||
> | |||
指标 | |||
</div> | |||
<div style="width: 40%; flex: 1; font-size: 16px; color: #333333"> | |||
<div v-if="zhixingcenterindex == 0" class="xiaojaingBox"> | |||
<div class="xiaojiang-title"> | |||
<div class="label1">指标</div> | |||
<div class="labe2"> | |||
<div style="width: 60px; text-align: center">执行</div> | |||
</div> | |||
</div> | |||
</div> | |||
<!-- 销讲 --> | |||
<div id="zxldiv" v-if="zhixingcenterindex == 0"> | |||
<div class="zxlBox" v-for="(item, index) in ratelist" :key="index"> | |||
<div class="zxlLev1" @click="changeshow(index)"> | |||
@@ -616,7 +603,7 @@ | |||
</div> | |||
</div> | |||
</div> | |||
<!-- 禁忌执行 --> | |||
<div | |||
id="zxldiv" | |||
v-if="zhixingcenterindex == 1" | |||
@@ -630,6 +617,204 @@ | |||
{{ index + 1 }}、{{ item }} | |||
</div> | |||
</div> | |||
<!-- 需求挖掘 --> | |||
<div v-if="zhixingcenterindex == 2" class="wajueBox"> | |||
<div style="display: flex"> | |||
<div style="padding: 0 10px; flex: 1; line-height: 44px"> | |||
挖掘执行率 {{ userinformationlist.wordFraction || 0 }}% | |||
</div> | |||
<div style="padding: 0 10px; flex: 1; line-height: 44px"> | |||
挖掘成功率 {{ userinformationlist.wordFinishFraction || 0 }}% | |||
</div> | |||
</div> | |||
<div class="wajue-title"> | |||
<div class="label1">指标</div> | |||
<div class="label2">执行</div> | |||
<div class="label3">匹配标签</div> | |||
</div> | |||
</div> | |||
<div | |||
id="zxldiv" | |||
style="height: calc(70vh - 230px)" | |||
v-if="zhixingcenterindex == 2" | |||
> | |||
<div | |||
style="width: 100%" | |||
v-for="(item, index) in keyWordsList" | |||
:key="index" | |||
> | |||
<!-- 有二级--> | |||
<div v-if="item.children.length"> | |||
<div | |||
class="rateboxcenttit" | |||
@click="changeshow1(item)" | |||
style="cursor: pointer" | |||
> | |||
<div style="flex: 1">{{ item.name }}</div> | |||
<div style="flex: 1">执行{{ item.fraction || 0 }}%</div> | |||
<div | |||
style="flex: 1" | |||
v-if="item.keywordsList && item.keywordsList.length" | |||
> | |||
已匹配({{ item.keywordsList && item.keywordsList.length }}) | |||
</div> | |||
<div style="flex: 1" v-else>未匹配</div> | |||
<div style="flex: 0 0 18px"> | |||
<i | |||
v-if="item.show" | |||
style="font-size: 18px" | |||
class="el-icon-arrow-up" | |||
></i> | |||
<i | |||
v-else | |||
style="font-size: 18px" | |||
class="el-icon-arrow-down" | |||
></i> | |||
</div> | |||
</div> | |||
<div | |||
v-if="item.show" | |||
v-for="(subitem, i) in item.children" | |||
:key="i" | |||
> | |||
<el-tooltip placement="bottom" effect="light"> | |||
<div slot="content"> | |||
<div class="huashu-title"> | |||
客户标签:{{ getKeywordsList(subitem.keywordsList) }} | |||
</div> | |||
<div class="huashu-title">需求挖掘话术</div> | |||
<div class="huashu"> | |||
<div | |||
class="huashu-item" | |||
v-for="(question, questionindex) in subitem.modelList" | |||
:key="questionindex" | |||
> | |||
<i | |||
class="el-icon-success" | |||
:style=" | |||
question.isAskQuestions == 0 | |||
? 'color: #409eff' | |||
: question.isAskQuestions == 2 | |||
? 'color: orange' | |||
: 'color: #666' | |||
" | |||
></i> | |||
<div | |||
class="text" | |||
:style=" | |||
question.isAskQuestions == 0 | |||
? 'color: #409eff' | |||
: question.isAskQuestions == 2 | |||
? 'color: orange' | |||
: 'color:#666' | |||
" | |||
> | |||
{{ | |||
question.showFormatExpression || | |||
question.keywordsName | |||
}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="rateboxcent"> | |||
<div>{{ subitem.name }}</div> | |||
<div> | |||
<div | |||
class="ratebutton" | |||
v-if="subitem.isAskQuestions == 0" | |||
> | |||
已执行 | |||
</div> | |||
<div class="ratebutton1" v-else>未执行</div> | |||
</div> | |||
<div> | |||
<div class="ratebutton" v-if="subitem.selected == 0"> | |||
已匹配 | |||
</div> | |||
<div class="ratebutton1" v-else>未匹配</div> | |||
</div> | |||
<div style="flex: 0 0 18px"></div> | |||
</div> | |||
</el-tooltip> | |||
</div> | |||
</div> | |||
<!-- 只有一级标签 --> | |||
<div v-if="item.children.length == 0"> | |||
<div class="rateboxcenttit" style="cursor: pointer"> | |||
<el-tooltip placement="bottom" effect="light"> | |||
<div slot="content"> | |||
<div class="huashu-title"> | |||
客户标签:{{ getKeywordsList(item.keywordsList) }} | |||
</div> | |||
<div class="huashu-title">需求挖掘话术</div> | |||
<div class="huashu"> | |||
<div | |||
class="huashu-item" | |||
v-for="(question, index) in item.modelList" | |||
:key="index" | |||
> | |||
<i | |||
class="el-icon-success" | |||
:style=" | |||
question.isAskQuestions == 0 | |||
? 'color: #409eff' | |||
: question.isAskQuestions == 2 | |||
? 'color: orange' | |||
: 'color: #666' | |||
" | |||
></i> | |||
<div | |||
class="text" | |||
:style=" | |||
question.isAskQuestions == 0 | |||
? 'color: #409eff' | |||
: question.isAskQuestions == 2 | |||
? 'color: orange' | |||
: 'color: #666' | |||
" | |||
> | |||
{{ | |||
question.showFormatExpression || | |||
question.keywordsName | |||
}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div style="display: flex"> | |||
<div style="flex: 1">{{ item.name }}</div> | |||
<div style="flex: 1">执行{{ item.fraction || 0 }}%</div> | |||
<div | |||
style="flex: 1" | |||
v-if="item.keywordsList && item.keywordsList.length" | |||
> | |||
已匹配({{ | |||
item.keywordsList && item.keywordsList.length | |||
}}) | |||
</div> | |||
<div style="flex: 1" v-else>未匹配</div> | |||
<div style="flex: 0 0 18px"></div> | |||
</div> | |||
</el-tooltip> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="mydesc" v-if="zhixingcenterindex == 2"> | |||
<span style="color: #409eff" | |||
><i class="el-icon-success" style="margin-right: 5px"></i | |||
>本次接待执行</span | |||
> | |||
<span style="color: orange" | |||
><i class="el-icon-success" style="margin-right: 5px"></i | |||
>之前接待执行</span | |||
> | |||
<span style="color: gray" | |||
><i class="el-icon-success" style="margin-right: 5px"></i | |||
>未执行</span | |||
> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -898,8 +1083,6 @@ | |||
</div> | |||
<div class="avatar"> | |||
<div :style="[spackerColor1(item.speaker)]"> | |||
<!-- <img style="margin: 0 auto" v-if="item.isShow == 1" | |||
src="http://121.42.63.138:9091/autoSR/static/plugins/audio/images/A.png" alt="" /> --> | |||
<div>{{ item.speaker | toCapital }}</div> | |||
</div> | |||
</div> | |||
@@ -1105,6 +1288,14 @@ import { saveAs } from "file-saver"; | |||
export default { | |||
data() { | |||
return { | |||
keyWordsList: [], | |||
imgArr: [ | |||
"", | |||
"https://static.quhouse.com/37e0de3f8d1c421dac8bf699d5e7992d.png", | |||
"https://static.quhouse.com/b106e8e75db24a59a579a15a78830a76.png", | |||
"https://static.quhouse.com/8443a2ecb81d4639991ab29c422e9949.png", | |||
"https://static.quhouse.com/1cd794cb6c974d9dad948a6dd444518b.png", | |||
], | |||
mg: 0, | |||
recordsText: [], | |||
roleVisible: false, | |||
@@ -1192,12 +1383,12 @@ export default { | |||
this.rec_index_todo = this.permissions["rec_index_todo"]; //禁忌 | |||
this.rec_index_receflag = this.permissions["rec_index_receflag"]; //接待标记 | |||
this.rec_index_textyh = this.permissions["rec_index_textyh"]; //文本优化 | |||
console.log(this.permissions); | |||
}, | |||
mounted() { | |||
this.fileId = this.$route.query.flag; | |||
this.AudioIdx = this.$route.query.AudioIdx; | |||
this.info = getStore({ name: "userInfo" }); | |||
this.findKeyWordsBycusId(); | |||
this.init(); | |||
}, | |||
computed: { | |||
@@ -1259,6 +1450,67 @@ export default { | |||
}, | |||
methods: { | |||
changeshow1(item) { | |||
item.show = !item.show; | |||
}, | |||
//挖掘率话术客户标签展示 | |||
getKeywordsList(list) { | |||
let keywords = []; | |||
if (list && list.length) { | |||
keywords = list.map((item) => item.name); | |||
} else { | |||
return "--"; | |||
} | |||
return keywords.join(","); | |||
}, | |||
//需求挖掘率-需求话术 | |||
findKeyWordsBycusId() { | |||
axios({ | |||
url: `/autoSR/customer/findKeyWordsBycusId`, | |||
method: "get", | |||
params: { | |||
cusId: this.fileId, | |||
}, | |||
}).then((data) => { | |||
if (data.code == 0) { | |||
console.log(data); | |||
let tempData = data.data; | |||
if (tempData.length) { | |||
tempData.forEach((item, index) => { | |||
item.show = false; | |||
if (index == 0) { | |||
item.show = true; | |||
} | |||
}); | |||
} else { | |||
tempData = []; | |||
} | |||
this.keyWordsList = tempData; | |||
console.log(this.keyWordsList); | |||
} | |||
}); | |||
}, | |||
// 对话加命中标签,区分类型的处理 | |||
dealTypes(type) { | |||
if (type) { | |||
// let tem = type.substring(1).split(',') | |||
let tem = type.split(","); | |||
return tem; | |||
} else { | |||
return []; | |||
} | |||
}, | |||
// 对话加命中标签-区分同一个类型的标签 | |||
dealword(type) { | |||
if (type) { | |||
let a = type.split("-"); | |||
let rest = type.substring(2).split("-").join(","); | |||
let arr = [a[0], rest]; | |||
return arr; | |||
} else { | |||
return []; | |||
} | |||
}, | |||
chooseRoles(index) { | |||
this.roleFlag = index; | |||
}, | |||
@@ -1278,7 +1530,7 @@ export default { | |||
}); | |||
}); | |||
console.log(this.outSpeechSkillList); | |||
// console.log(this.outSpeechSkillList); | |||
}, | |||
// 导出word | |||
@@ -1521,7 +1773,7 @@ export default { | |||
} else { | |||
this.aplayerId = idx; | |||
this.aplayer.destroy(); | |||
console.log(idx); | |||
// console.log(idx); | |||
this.transcriptionlist = JSON.parse(this.arr[idx].audioContent); | |||
this.recordPath = this.arr[idx].recordPath; | |||
this.bofangchushihua(); | |||
@@ -1592,6 +1844,7 @@ export default { | |||
saveType: i, | |||
corpusId: this.arr[this.aplayerId].id, | |||
id: this.optimizeobj.id, | |||
customerId: this.fileId, | |||
textContent: JSON.stringify(this.optimizetext), | |||
}) | |||
.then((res) => { | |||
@@ -1774,6 +2027,7 @@ export default { | |||
let param = { | |||
keywordIds: "", | |||
id: this.fileId, | |||
projectId: this.userinformationlist.projectId, | |||
}; | |||
let str = []; | |||
this.Acquirecustomerintentlist2.map((item) => { | |||
@@ -1931,6 +2185,7 @@ export default { | |||
}) | |||
.then((res) => { | |||
this.$message.success("保存成功"); | |||
this.init(); | |||
}); | |||
}, | |||
@@ -1972,10 +2227,6 @@ export default { | |||
console.log(this.mistakenList, this.correctList); | |||
}); | |||
}, | |||
// 销讲词禁忌tab | |||
recordclick(i) { | |||
this.zhixingcenterindex = i; | |||
}, | |||
// 销讲词折叠 | |||
changeshow(index) { | |||
this.ratelist[index].show = !this.ratelist[index].show; | |||
@@ -2114,42 +2365,48 @@ export default { | |||
//获取转写内容和播放列表 | |||
Getsthetransliteratecontent() { | |||
this.$api.http.findByCusIdcusId({ cusId: this.fileId }).then((res) => { | |||
let audopbj = res.data; | |||
this.mg = res.data[0].merge; | |||
this.recordPath = audopbj[this.AudioIdx].recordPath; | |||
audopbj[this.AudioIdx].audioContent != "" | |||
? (this.transcriptionlist = JSON.parse( | |||
audopbj[this.AudioIdx].audioContent | |||
)) | |||
: (this.transcriptionlist = []); | |||
// this.transcriptionlist=JSON.parse(audopbj[this.AudioIdx].audioContent) | |||
this.tablist = []; | |||
if (this.userinformationlist.yon == 0) { | |||
this.isd = audopbj[this.AudioIdx].id; | |||
console.log(audopbj[this.AudioIdx].speakerNum, "speakerNum"); | |||
this.creatTabList(audopbj[this.AudioIdx].speakerNum) | |||
this.roleList = this.tablist.slice(1); | |||
if (audopbj[this.AudioIdx].speaker == null) { | |||
this.yibiaoji = "未标记"; | |||
this.roleindexbiaoji = 0; | |||
this.dshfkjsdkksodofydwfkhwdfkjh = 0; | |||
} else { | |||
this.yibiaoji = "已标记"; | |||
this.tablist[audopbj[this.AudioIdx].speaker].name = | |||
this.tablist[audopbj[this.AudioIdx].speaker].name + "顾问"; | |||
this.roleindexbiaoji = audopbj[this.AudioIdx].speaker - 1; | |||
this.dshfkjsdkksodofydwfkhwdfkjh = | |||
audopbj[this.AudioIdx].speaker - 1; | |||
this.$api.http | |||
.findByCusIdcusId({ | |||
cusId: this.fileId, | |||
}) | |||
.then((res) => { | |||
console.log(res, "dsadasd"); | |||
let audopbj = res.data; | |||
this.mg = res.data[0].merge; | |||
console.log(res.data[0].merge, "res.data[0].merge"); | |||
this.recordPath = audopbj[this.AudioIdx].recordPath; | |||
audopbj[this.AudioIdx].audioContent != "" | |||
? (this.transcriptionlist = JSON.parse( | |||
audopbj[this.AudioIdx].audioContent | |||
)) | |||
: (this.transcriptionlist = []); | |||
// this.transcriptionlist=JSON.parse(audopbj[this.AudioIdx].audioContent) | |||
this.tablist = []; | |||
if (this.userinformationlist.yon == 0) { | |||
this.isd = audopbj[this.AudioIdx].id; | |||
// console.log(audopbj[this.AudioIdx].speakerNum, "speakerNum"); | |||
this.creatTabList(audopbj[this.AudioIdx].speakerNum); | |||
this.roleList = this.tablist.slice(1); | |||
if (audopbj[this.AudioIdx].speaker == null) { | |||
this.yibiaoji = "未标记"; | |||
this.roleindexbiaoji = 0; | |||
this.dshfkjsdkksodofydwfkhwdfkjh = 0; | |||
} else { | |||
this.yibiaoji = "已标记"; | |||
this.tablist[audopbj[this.AudioIdx].speaker].name = | |||
this.tablist[audopbj[this.AudioIdx].speaker].name + "顾问"; | |||
this.roleindexbiaoji = audopbj[this.AudioIdx].speaker - 1; | |||
this.dshfkjsdkksodofydwfkhwdfkjh = | |||
audopbj[this.AudioIdx].speaker - 1; | |||
} | |||
} | |||
} | |||
this.corpusId = audopbj[this.AudioIdx].id; | |||
this.aplayerId = this.AudioIdx; | |||
this.aplayerLength = audopbj.length; | |||
this.arr = res.data; | |||
this.bofangchushihua(); | |||
this.formatAudioList(); | |||
}); | |||
this.corpusId = audopbj[this.AudioIdx].id; | |||
this.aplayerId = this.AudioIdx; | |||
this.aplayerLength = audopbj.length; | |||
this.arr = res.data; | |||
this.bofangchushihua(); | |||
this.formatAudioList(); | |||
}); | |||
}, | |||
tapspagek(data, index) { | |||
// this.roleindex = i | |||
@@ -2242,7 +2499,7 @@ export default { | |||
download() { | |||
console.log(this.recordPath); | |||
saveAs( | |||
`http://81.70.55.170:9999/autoSR/zk/file/filedownload?videoSrc=${this.recordPath}`, | |||
`http://39.97.244.65:9999/autoSR/zk/file/filedownload?videoSrc=${this.recordPath}`, | |||
"audio.mp3" | |||
); | |||
return; | |||
@@ -2259,7 +2516,6 @@ export default { | |||
responseType: "blob", | |||
}) | |||
.then((res) => { | |||
console.log(res, "adasdjslakd"); | |||
let blob = new Blob([res], { type: "audio/*" }); | |||
saveAs(blob, "audio.mp3"); | |||
@@ -2272,7 +2528,7 @@ export default { | |||
// // 使用获取到的blob对象创建的url | |||
// const url = window.URL.createObjectURL(res); | |||
// a.href = url; | |||
// // 指定下载的文件名,就‘’写默认的下载名字。不指定他就根据上传名直接下载了宝。 | |||
// // 指定下载的文件名,就‘’写默认的下载名字。不指定他就根据上传名直接下载了。 | |||
// a.download = ''; | |||
// a.click(); | |||
// document.body.removeChild(a) | |||
@@ -2289,6 +2545,193 @@ export default { | |||
</script> | |||
<style scoped lang="scss" > | |||
/deep/.el-radio-button__orig-radio:checked + .el-radio-button__inner { | |||
background-color: #2671e2 !important; | |||
border-color: #2671e2 !important; | |||
} | |||
/deep/.el-radio-button--small .el-radio-button__inner { | |||
padding: 9px 10px !important; | |||
} | |||
.rateboxcenttit { | |||
width: 100%; | |||
height: 44px; | |||
background: #f8f8f8; | |||
display: flex; | |||
align-items: center; | |||
color: #333333; | |||
font-size: 16px; | |||
& > div { | |||
flex: 1; | |||
white-space: nowrap; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
text-align: center; | |||
} | |||
} | |||
.ratebutton { | |||
width: 68px; | |||
height: 26px; | |||
background: #2671e2; | |||
border-radius: 4px; | |||
font-size: 14px; | |||
font-weight: 400; | |||
color: #ffffff; | |||
text-align: center; | |||
line-height: 26px; | |||
margin: 0 auto; | |||
} | |||
.ratebutton1 { | |||
width: 68px; | |||
height: 26px; | |||
background: #f2f2f2; | |||
border-radius: 4px; | |||
font-size: 14px; | |||
font-weight: 400; | |||
color: #999999; | |||
text-align: center; | |||
line-height: 26px; | |||
margin: 0 auto; | |||
} | |||
// 销讲执行率 | |||
.xiaojaingBox { | |||
.xiaojiang-title { | |||
width: 100%; | |||
height: 44px; | |||
border-bottom: 1px solid #e0e0e0; | |||
display: flex; | |||
align-items: center; | |||
background: #f0f6ff; | |||
.label1 { | |||
width: 60%; | |||
font-size: 16px; | |||
color: #333333; | |||
text-indent: 20px; | |||
} | |||
.label2 { | |||
width: 40%; | |||
flex: 1; | |||
font-size: 16px; | |||
color: #333333; | |||
} | |||
} | |||
} | |||
// 需求挖掘率 | |||
.wajueBox { | |||
.wajue-title { | |||
width: 100%; | |||
height: 44px; | |||
border-bottom: 1px solid #e0e0e0; | |||
display: flex; | |||
align-items: center; | |||
background: #f0f6ff; | |||
.label1 { | |||
width: 40%; | |||
font-size: 16px; | |||
color: #333333; | |||
text-indent: 20px; | |||
} | |||
.label2 { | |||
width: 20%; | |||
flex: 1; | |||
font-size: 16px; | |||
color: #333333; | |||
} | |||
.label3 { | |||
width: 40%; | |||
flex: 1; | |||
font-size: 16px; | |||
color: #333333; | |||
} | |||
} | |||
} | |||
/*话术*/ | |||
.huashu-title { | |||
background: #fff; | |||
font-size: 16px; | |||
line-height: 20px; | |||
padding: 10px 20px; | |||
} | |||
.huashu { | |||
width: 260px; | |||
padding: 0 20px 30px; | |||
display: flex; | |||
align-items: center; | |||
flex-wrap: wrap; | |||
background: #fff; | |||
.huashu-item { | |||
margin-right: 20px; | |||
height: 30px; | |||
line-height: 30px; | |||
display: flex; | |||
align-items: center; | |||
.text { | |||
font-size: 14px; | |||
color: #666; | |||
margin-left: 5px; | |||
} | |||
} | |||
} | |||
.rateboxcent { | |||
width: 100%; | |||
height: 50px; | |||
border-bottom: 1px solid #f8f8f8; | |||
display: flex; | |||
align-items: center; | |||
color: #666666; | |||
font-size: 14px; | |||
& > div { | |||
flex: 1; | |||
text-align: center; | |||
white-space: nowrap; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
} | |||
} | |||
.mydesc { | |||
position: absolute; | |||
bottom: 0; | |||
left: 0; | |||
right: 0; | |||
padding: 0 10px; | |||
height: 40px; | |||
border-top: 1px solid #ccc; | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
background: #fff; | |||
} | |||
/*对话的标签标识*/ | |||
.content123 .showmark { | |||
font-size: 14px; | |||
min-height: 20px; | |||
line-height: 20px; | |||
margin: 10px 22px 0; | |||
display: flex; | |||
flex-direction: column; | |||
.mark-item { | |||
display: flex; | |||
align-items: flex-start; | |||
margin-bottom: 2px; | |||
.markicon { | |||
width: 14px; | |||
height: 14px; | |||
margin-right: 6px; | |||
} | |||
.marktext { | |||
font-size: 12px; | |||
font-family: PingFangSC-Regular, PingFang SC; | |||
font-weight: 400; | |||
color: #3e50e8; | |||
line-height: 18px; | |||
word-break: break-all; | |||
margin: 0; | |||
max-width: 150px; | |||
} | |||
} | |||
} | |||
.expIcon { | |||
display: block; | |||
width: 16px; | |||
@@ -2302,9 +2745,10 @@ export default { | |||
} | |||
#zxldiv { | |||
height: calc(70vh - 220px); | |||
// padding-bottom: 50px; | |||
overflow-y: scroll; | |||
// height: 100%; | |||
height: calc(70vh - 248px); | |||
position: relative; | |||
} | |||
.biaotibox { | |||
@@ -2357,7 +2801,6 @@ export default { | |||
width: 100%; | |||
height: 95%; | |||
min-width: 1000px; | |||
// padding-bottom: 100px; | |||
background: #ffffff; | |||
} | |||
@@ -2388,7 +2831,7 @@ export default { | |||
font-size: 12px; | |||
line-height: 20px; | |||
display: flex; | |||
align-items: center; | |||
// align-items: center; | |||
margin: 18px 0px; | |||
position: relative; | |||
} | |||
@@ -2406,6 +2849,10 @@ export default { | |||
flex-direction: row-reverse; | |||
text-align: left; | |||
} | |||
.showmark { | |||
flex-direction: row-reverse; | |||
text-align: left; | |||
} | |||
} | |||
.content123 .content123s { | |||
@@ -2438,7 +2885,6 @@ export default { | |||
.center2 .text .avatar { | |||
width: 34px; | |||
height: 34px; | |||
// background-color: #ccc; | |||
border-radius: 50%; | |||
display: flex; | |||
justify-content: center; | |||
@@ -2480,7 +2926,7 @@ export default { | |||
font-size: 24px; | |||
display: flex; | |||
align-items: center; | |||
margin-top: 12px; | |||
// margin-top: 12px; | |||
justify-content: center; | |||
} | |||
@@ -2507,8 +2953,6 @@ export default { | |||
.center3 .text .avatar { | |||
width: 38px; | |||
height: 38px; | |||
/*background-color: #f2f2f2;*/ | |||
// background-color: #ccc; | |||
border-radius: 8px; | |||
margin-left: 15px; | |||
display: flex; | |||
@@ -2528,7 +2972,6 @@ export default { | |||
height: 100%; | |||
text-align: center; | |||
line-height: 38px; | |||
// color: #ffffff; | |||
font-size: 24px; | |||
border-radius: 4px; | |||
} | |||
@@ -2604,7 +3047,6 @@ export default { | |||
width: 94%; | |||
margin: 0 auto; | |||
padding-bottom: 12px; | |||
// border-bottom: 1px solid #e0e0e0; | |||
} | |||
.intentionChe { | |||
@@ -2863,7 +3305,6 @@ export default { | |||
.aplayer { | |||
box-shadow: none; | |||
/*width: 80%;*/ | |||
width: 95.3%; | |||
} | |||
@@ -2979,13 +3420,7 @@ export default { | |||
.searchbox54 .avatar { | |||
width: 40px; | |||
height: 40px; | |||
/*background-color: #f2f2f2;*/ | |||
// background-color: #ccc; | |||
border-radius: 4px; | |||
// margin-left: 5px; | |||
// display: flex; | |||
// justify-content: center; | |||
// align-items: center; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
@@ -2994,13 +3429,7 @@ export default { | |||
.searchbox54 .avatar div { | |||
width: 40px; | |||
height: 40px; | |||
/*background-color: #f2f2f2;*/ | |||
// background-color: #ccc; | |||
border-radius: 4px; | |||
// margin-left: 5px; | |||
// display: flex; | |||
// justify-content: center; | |||
// align-items: center; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
@@ -163,7 +163,6 @@ | |||
</el-option> | |||
</el-select> | |||
</div> | |||
<div class="div-lab" v-if="false"> | |||
<!-- 默认全部 --> | |||
<div class="label">是否违禁:</div> | |||
@@ -183,26 +182,6 @@ | |||
</el-option> | |||
</el-select> | |||
</div> | |||
<!-- <div class="div-lab"> | |||
<div class="label">是否加精:</div> | |||
<el-select | |||
v-model="searchForm.zfal" | |||
placeholder="请选择" | |||
class="div-inp" | |||
filterable | |||
clearable | |||
> | |||
<el-option | |||
v-for="item in options12" | |||
:key="item.value" | |||
:label="item.label" | |||
:value="item.value" | |||
> | |||
</el-option> | |||
</el-select> | |||
</div> --> | |||
<div class="div-lab"> | |||
<div class="label">接待时长:</div> | |||
<el-select | |||
@@ -258,15 +237,79 @@ | |||
</el-select> | |||
</div> | |||
<div class="div-lab"> | |||
<div class="label">销讲执行:</div> | |||
<el-select | |||
v-model="searchForm.fractions" | |||
class="div-inp" | |||
clearable | |||
filterable | |||
placeholder="请选择" | |||
> | |||
<el-option label="30%及以下" :value="1"></el-option> | |||
<el-option label="31%~50%" :value="2"></el-option> | |||
<el-option label="51%~70%" :value="3"></el-option> | |||
<el-option label="71%及以上" :value="4"></el-option> | |||
</el-select> | |||
</div> | |||
<div class="div-lab"> | |||
<div class="label">需求挖掘:</div> | |||
<el-select | |||
v-model="searchForm.wordFractions" | |||
class="div-inp" | |||
clearable | |||
filterable | |||
placeholder="请选择" | |||
> | |||
<el-option label="30%及以下" :value="1"></el-option> | |||
<el-option label="31%~50%" :value="2"></el-option> | |||
<el-option label="51%~70%" :value="3"></el-option> | |||
<el-option label="71%及以上" :value="4"></el-option> | |||
</el-select> | |||
</div> | |||
<div class="div-lab"> | |||
<div class="label">挖掘话术:</div> | |||
<el-select | |||
v-model="searchForm.questionId" | |||
clearable | |||
filterable | |||
placeholder="请选择" | |||
class="div-inp" | |||
> | |||
<el-option | |||
v-for="item in questionList" | |||
:key="item.id" | |||
:label="item.question" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</div> | |||
<div class="div-lab"> | |||
<div class="label">无效接待原因:</div> | |||
<el-select | |||
v-model="searchForm.invalidReason" | |||
clearable | |||
filterable | |||
placeholder="请选择" | |||
class="div-inp" | |||
> | |||
<el-option | |||
v-for="item in marketingInvalidList" | |||
:key="item.id" | |||
:label="item.name" | |||
:value="item.id" | |||
></el-option> | |||
</el-select> | |||
</div> | |||
<div class="div-lab" v-if="false"> | |||
<div class="label">销讲业务:</div> | |||
<el-select | |||
class="div-inp" | |||
v-model="searchForm.marketingBusiness" | |||
multiple | |||
clearable | |||
filterable | |||
collapse-tags | |||
placeholder="请选择" | |||
class="div-inpbox" | |||
> | |||
<el-option | |||
v-for="item in templateList" | |||
@@ -277,31 +320,31 @@ | |||
</el-option> | |||
</el-select> | |||
</div> | |||
</div> | |||
<div class="app-titel" style="margin-top: 15px"> | |||
<div style="margin-left: 110px"> | |||
<el-button type="primary" @click="screen">筛选</el-button> | |||
</div> | |||
<div style="margin-left: 20px"> | |||
<el-button @click="clearScreen" type="text">清空筛选条件</el-button> | |||
</div> | |||
<el-button style="margin-left: 10px" @click="isSystoleForm" type="text" | |||
>{{ isOpen ? "收起" : "展开" | |||
}}<i | |||
style="margin-left: 5px" | |||
:class="isOpen ? 'el-icon-arrow-up' : 'el-icon-arrow-down'" | |||
></i | |||
></el-button> | |||
<div class="app-titel" style="margin-top: 15px"> | |||
<div style="margin-left: 110px"> | |||
<el-button type="primary" @click="screen">筛选</el-button> | |||
</div> | |||
<div style="margin-left: 20px"> | |||
<el-button @click="clearScreen" type="text">清空筛选条件</el-button> | |||
</div> | |||
<el-button style="margin-left: 10px" @click="isSystoleForm" type="text" | |||
>{{ isOpen ? "收起" : "展开" | |||
}}<i | |||
style="margin-left: 5px" | |||
:class="isOpen ? 'el-icon-arrow-up' : 'el-icon-arrow-down'" | |||
></i | |||
></el-button> | |||
<div | |||
style="margin-left: auto; margin-right: 10px" | |||
v-if="rec_index_downLoad" | |||
> | |||
<el-button @click="downLoad" icon="el-icon-download"> 导出</el-button> | |||
</div> | |||
<div | |||
style="margin-left: auto; margin-right: 10px" | |||
v-if="rec_index_downLoad" | |||
> | |||
<el-button @click="downLoad" icon="el-icon-download"> 导出</el-button> | |||
</div> | |||
</div> | |||
</div> | |||
<!-- 表格 --> | |||
<div class="cen-tab"> | |||
@@ -322,9 +365,54 @@ | |||
@click="Receivedetailsabout(row)" | |||
>查看</el-button | |||
> | |||
<el-button | |||
type="text" | |||
v-if="rec_rewrite_show" | |||
@click="reWriteagain(row)" | |||
>重新转写</el-button | |||
> | |||
</template> | |||
</avue-crud> | |||
</div> | |||
<el-dialog | |||
title="重新转写" | |||
center | |||
:visible.sync="dialogVisible" | |||
width="50%" | |||
> | |||
<!-- <div style="text-align: center;font-size: 16px" v-if="mergeflag">请等待录音合并之后再重新转写!</div> --> | |||
<el-form :model="form"> | |||
<el-form-item label="转写方式" :label-width="80"> | |||
<el-select | |||
v-model="form.project" | |||
placeholder="请选择" | |||
@change="changeFun" | |||
> | |||
<el-option | |||
v-for="(item, index) in projectList" | |||
:label="item.name" | |||
:key="index" | |||
:value="item.code" | |||
></el-option> | |||
</el-select> | |||
<el-select v-model="form.language" placeholder="请选择"> | |||
<el-option | |||
v-for="(item, index) in languageList" | |||
:label="item.name" | |||
:key="index" | |||
:value="item.code" | |||
></el-option> | |||
</el-select> | |||
</el-form-item> | |||
<div style="color: red; margin-left: 60px"> | |||
提示:重新转写需要10分钟左右才能完成! | |||
</div> | |||
</el-form> | |||
<span slot="footer" class="dialog-footer"> | |||
<el-button @click="dialogVisible = false">取 消</el-button> | |||
<el-button type="primary" @click="checkFun">确 定</el-button> | |||
</span> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
@@ -334,6 +422,17 @@ import { exportMethodPost } from "@/util/util"; | |||
export default { | |||
data() { | |||
return { | |||
questionList: [], //挖掘话术 | |||
marketingInvalidList: [], // 无效接待原因列表 | |||
xiaojianglist: [], //销讲业务 | |||
desc: "请等待录音合并之后再重新转写!", | |||
dialogVisible: false, | |||
projectList: [], | |||
languageList: [], | |||
form: { | |||
language: "", | |||
project: "", | |||
}, //重新转写 | |||
tableIdName: "ReceivingRecordsIndex", // 当前页面需要的变量 | |||
tableOption: this.$tableOption.ReceivingRecordsIndex, // 当前table配置项 | |||
tableLoading: false, // 是否显示加载中 | |||
@@ -430,23 +529,7 @@ export default { | |||
label: "是", | |||
}, | |||
], | |||
options12: [ | |||
{ | |||
value: "0", | |||
label: "已加精", | |||
}, | |||
{ | |||
value: "1", | |||
label: "未加精", | |||
}, | |||
], | |||
options13: [ | |||
{ | |||
label: "全部", | |||
value: "", | |||
}, | |||
{ | |||
label: "有效接待", | |||
value: "0", | |||
@@ -456,23 +539,6 @@ export default { | |||
value: "1", | |||
}, | |||
], | |||
options14: [ | |||
// 正反案例 | |||
{ | |||
label: "全部", | |||
value: "", | |||
}, | |||
{ | |||
label: "正面案例", | |||
value: "0", | |||
}, | |||
{ | |||
label: "反面案例", | |||
value: "1", | |||
}, | |||
], | |||
value: "", | |||
input: "", | |||
tableData: [], | |||
@@ -494,12 +560,16 @@ export default { | |||
zfal: "", // 正反案例 0:正面案例 1:反面案例 | |||
validInvalid: "", // 是否为有效接待 0:有效 1:无效 | |||
marketingBusiness: [], | |||
invalidReason: "", | |||
question: "", | |||
wordFractions: "", | |||
fractions: "", | |||
}, | |||
rec_index_show: false, // 按钮权限 | |||
rec_rewrite_show: false, // 重新转写-按钮权限 | |||
rec_index_text: false, // 按钮权限 | |||
rec_index_voice: false, // 按钮权限 | |||
rec_index_downLoad: false, // 按钮权限 | |||
templateList: [], // 销讲业务列表 | |||
}; | |||
}, | |||
@@ -612,6 +682,7 @@ export default { | |||
} | |||
this.rec_index_show = this.permissions["rec_index_show"]; | |||
this.rec_rewrite_show = this.permissions["rec_rewrite_show"]; | |||
this.rec_index_text = this.permissions["rec_index_text"]; | |||
this.rec_index_voice = this.permissions["rec_index_voice"]; | |||
this.rec_index_downLoad = this.permissions["rec_index_downLoad"]; | |||
@@ -622,6 +693,84 @@ export default { | |||
}, | |||
methods: { | |||
// 获取话术 | |||
findQuestionList() { | |||
axios({ | |||
url: `/autoSR/zk/keywords/findQuestionList`, | |||
method: "get", | |||
params: { | |||
houseId: this.searchForm.projectId, | |||
}, | |||
}).then((data) => { | |||
if (data.code == 0) { | |||
this.questionList = data.data; | |||
} | |||
}); | |||
}, | |||
// 无效接待原因列表 | |||
getMarketingInvalidList() { | |||
this.$api.api.invalidList({ houseId: this.houseId }).then((res) => { | |||
if (res.data && res.data.obj) { | |||
this.marketingInvalidList = res.data.obj; | |||
} else { | |||
this.marketingInvalidList = []; | |||
} | |||
}); | |||
}, | |||
// 转写方式切换 | |||
changeFun(value) { | |||
// console.log(value) | |||
this.form.language = ""; | |||
this.projectList.forEach((item) => { | |||
if (item.code == value) { | |||
this.languageList = item.list; | |||
this.form.language = this.languageList[0].code; | |||
} | |||
}); | |||
}, | |||
// 转写方式数据获取 | |||
findTransferMethod() { | |||
this.$api.api.findTransferMethod().then((res) => { | |||
if (res.data && res.data.obj) { | |||
this.projectList = res.data.data || []; | |||
this.languageList = (res.data.data && res.data.data[0].list) || []; | |||
} | |||
}); | |||
}, | |||
// 确定重新转写 | |||
checkFun() { | |||
if (this.form.project === "" || this.form.language === "") { | |||
this.$message.error("请先选择转写方式"); | |||
return; | |||
} | |||
this.$api.api | |||
.toTransferData({ | |||
id: this.currentRow.id, | |||
transferMethod: this.form.project, | |||
transferLanguage: this.form.language, | |||
}) | |||
.then((res) => { | |||
this.dialogVisible = false; | |||
this.getorgCode(); | |||
this.$message.success("操作成功"); | |||
}); | |||
}, | |||
reWriteagain(row) { | |||
this.dialogVisible = true; | |||
this.currentRow = row; | |||
// mergeFlag; //是否合并 0是 1 否 | |||
this.form.project = row.transferMethod || ""; | |||
if (row.transferLanguage) { | |||
this.projectList.forEach((item) => { | |||
if (item.code == row.transferLanguage) { | |||
this.languageList = item.list; | |||
this.form.language = row.transferLanguage || ""; | |||
} | |||
}); | |||
} else { | |||
this.form.language = ""; | |||
} | |||
}, | |||
// 获取销讲业务 | |||
getMarketingBusiness() { | |||
this.$api.http | |||
@@ -694,16 +843,18 @@ export default { | |||
obj.projectId = this.$route.query.houseId; | |||
} | |||
obj.keywordIds = obj.keywordsId.join(","); | |||
obj.marketingBusiness = obj.marketingBusiness.join(',') | |||
obj.marketingBusiness = obj.marketingBusiness.join(","); | |||
obj.dateType = this.searchForm.staDate ? null : this.searchForm.dateType; | |||
this.$api.api.findbypage(obj).then((res) => { | |||
console.log(res); | |||
this.tableData = res.data.records; | |||
this.page.total = res.data.total; | |||
// 表格中设置ref属性,在数据渲染之后或者updated()之后 | |||
this.$nextTick(() => { | |||
this.$refs.crud.doLayout(); | |||
}); | |||
// console.log(res); | |||
if (res.code == 0) { | |||
this.tableData = res.data.records||[]; | |||
this.page.total = res.data.total; | |||
// 表格中设置ref属性,在数据渲染之后或者updated()之后 | |||
this.$nextTick(() => { | |||
this.$refs.crud.doLayout(); | |||
}); | |||
} | |||
}); | |||
}, | |||
clearScreen() { | |||
@@ -720,9 +871,11 @@ export default { | |||
houseType: "", | |||
dateType: null, | |||
taboo: "", | |||
questionId: "", | |||
fraction: "", | |||
wordFraction: "", | |||
marketingBusiness: [], | |||
zfal: "", | |||
// projectId: this.houseList[0].id, | |||
projectId: | |||
this.orgType == 3 | |||
? localStorage.getItem("houseId") | |||
@@ -736,6 +889,8 @@ export default { | |||
houseChange() { | |||
this.findbypage(); | |||
this.findKeywords(); | |||
this.findQuestionList(); | |||
// this.getMarketingBusiness();// 销讲业务 | |||
// 获取置业顾问列表 | |||
this.findUserListByHouseId(); | |||
}, | |||
@@ -745,7 +900,6 @@ export default { | |||
this.searchForm.staDate = ""; | |||
this.searchForm.endDate = ""; | |||
} else { | |||
console.log(e, "asdkasljdlksajl"); | |||
this.searchForm.dateType = null; | |||
this.searchForm.staDate = e[0]; | |||
this.searchForm.endDate = e[1]; | |||
@@ -755,7 +909,6 @@ export default { | |||
}, | |||
screen() { | |||
this.page.currentPage = 1; | |||
console.log(this.searchForm); | |||
this.findbypage(); | |||
}, | |||
findKeywords() { | |||
@@ -768,7 +921,6 @@ export default { | |||
type: this.type, | |||
}) | |||
.then((res) => { | |||
console.log(res); | |||
this.keywordsList = res.data; | |||
}); | |||
}, | |||
@@ -792,7 +944,7 @@ export default { | |||
this.houseChange(); | |||
// 获取销讲业务 | |||
this.getMarketingBusiness(); | |||
// this.getMarketingBusiness(); | |||
}); | |||
}, | |||
// 置业顾问列表 | |||
@@ -801,16 +953,13 @@ export default { | |||
orgType: localStorage.getItem("orgType"), | |||
projectId: this.searchForm.projectId, | |||
}); | |||
console.log(result); | |||
this.accountList = result.data; | |||
}, | |||
handleSizeChange(val) { | |||
console.log(`每页 ${val} 条`); | |||
this.page.pageSize = val; | |||
this.findbypage(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log(`当前页: ${val}`); | |||
this.page.currentPage = val; | |||
this.findbypage(); | |||
}, | |||
@@ -867,7 +1016,7 @@ export default { | |||
}; | |||
</script> | |||
<style scoped="scoped" lang="scss" > | |||
<style scoped="scoped" lang="scss"> | |||
.box-center { | |||
width: 100%; | |||
padding: 5px 15px 40px; | |||
@@ -905,7 +1054,7 @@ export default { | |||
font-weight: 400; | |||
color: #32363d; | |||
line-height: 32px; | |||
min-width: 100px; | |||
min-width: 120px; | |||
text-align: right; | |||
} | |||
@@ -21,13 +21,12 @@ export default { | |||
{ | |||
sortable: true, | |||
label: '接待开始时间', | |||
prop: 'staTimeOfCN', | |||
prop: 'createTime', | |||
}, | |||
{ | |||
label: "顾问", | |||
prop: "agentName", | |||
}, | |||
{ | |||
label: "客户", | |||
prop: "name", | |||
@@ -58,6 +57,47 @@ export default { | |||
return data.markAdvisor == 0 ? "未标记" : '已标记' | |||
} | |||
}, | |||
{ | |||
sortable: true, | |||
label: "挖掘执行率", | |||
prop: "wordFraction", | |||
formatter: data => { | |||
return (data.wordFraction||0) + '%' | |||
} | |||
}, | |||
{ | |||
label: "无效接待原因", | |||
prop: "invalidReason", | |||
formatter: data => { | |||
let str = '' | |||
switch (data.invalidReason) { | |||
case 1 : | |||
str = '没电指派无录音' | |||
break; | |||
case 2 : | |||
str = '离线指派无录音' | |||
break; | |||
case 3 : | |||
str = '系统测试误操作' | |||
break; | |||
case 4 : | |||
str = '非接访场景录音' | |||
break; | |||
case 5 : | |||
str = '其它' | |||
break; | |||
case 6 : | |||
str = '离线' | |||
break; | |||
case 7 : | |||
str = '无设备' | |||
break; | |||
default : | |||
break; | |||
} | |||
return str | |||
} | |||
}, | |||
{ | |||
label: "销讲业务", | |||
@@ -66,15 +106,17 @@ export default { | |||
{ | |||
sortable: true, | |||
label: "画像标签触达次数", | |||
prop: "total", | |||
width: '150px', | |||
label: "挖掘成功率", | |||
prop: "wordFinishFraction", | |||
formatter: data => { | |||
return (data.wordFinishFraction||0) + '%' | |||
} | |||
}, | |||
{ | |||
sortable: true, | |||
label: "执行率", | |||
prop: "total", | |||
prop: "fraction", | |||
formatter: data => { | |||
return `${data.fraction || 0}%` | |||
} | |||
@@ -24,8 +24,8 @@ | |||
</div> | |||
<div class="app-titel projectBackend"> | |||
<div class="titel-text">筛选日期:</div> | |||
<div style="margin-left: 14px"> | |||
<div class="titel-text">日期:</div> | |||
<div style="margin-left: 10px"> | |||
<el-button | |||
:class="{ 'el-button--primary': TimetoAhoose == 0 }" | |||
@click="tabtimetap(0)" | |||
@@ -42,8 +42,9 @@ | |||
>近30天</el-button | |||
> | |||
</div> | |||
<div style="margin-left: 26px"> | |||
<div style="margin-left: 10px"> | |||
<el-date-picker | |||
style="width:300px" | |||
v-model="customtime" | |||
@change="confirmtime()" | |||
type="daterange" | |||
@@ -57,7 +58,7 @@ | |||
</el-date-picker> | |||
</div> | |||
<div style="margin-left: 26px;" class="div-lab"> | |||
<div style="margin-left: 20px;" class="div-lab"> | |||
<div class="label">顾问:</div> | |||
<el-select | |||
v-model="consultantlistid" | |||
@@ -74,7 +75,7 @@ | |||
</el-option> | |||
</el-select> | |||
</div> | |||
<div style="margin-left: 26px" class="div-lab"> | |||
<div style="margin-left: 20px" class="div-lab"> | |||
<div class="label">对比:</div> | |||
<el-select | |||
v-model="Pklistid" | |||
@@ -1482,14 +1483,14 @@ export default { | |||
margin: 5px; | |||
} | |||
.div-inp { | |||
width: 200px; | |||
width: 180px; | |||
} | |||
.label { | |||
font-size: 16px; | |||
font-weight: 400; | |||
color: #32363d; | |||
line-height: 32px; | |||
min-width: 40px; | |||
min-width: 50px; | |||
} | |||
.noData { | |||
width: 100%; | |||
@@ -21,34 +21,6 @@ | |||
</el-select> | |||
</div> | |||
</div> | |||
<!-- <div class="app-titel"> | |||
<div style="text-indent: 30px; font-weight: bold">接待时间:</div> | |||
<div class="toptimeqhuan"> | |||
<div :class="{ tophove: TimetoAhoose == 4 }" @click="tabtimetap(4)"> | |||
近7天 | |||
</div> | |||
<div :class="{ tophove: TimetoAhoose == 5 }" @click="tabtimetap(5)"> | |||
近15天 | |||
</div> | |||
<div :class="{ tophove: TimetoAhoose == 6 }" @click="tabtimetap(6)"> | |||
近30天 | |||
</div> | |||
</div> | |||
<div style="margin-left: 26px"> | |||
<el-date-picker | |||
@change="confirmtime()" | |||
v-model="customtime" | |||
type="daterange" | |||
range-separator="-" | |||
:default-time="['00:00:00', '23:59:59']" | |||
value-format="yyyy-MM-dd" | |||
start-placeholder="开始日期" | |||
end-placeholder="结束日期" | |||
:picker-options="pickerOptions" | |||
> | |||
</el-date-picker> | |||
</div> | |||
</div> --> | |||
<div class="app-titel projectBackend"> | |||
<div class="titel-text">筛选日期:</div> | |||
<div style="margin-left: 14px"> | |||
@@ -311,7 +283,6 @@ | |||
<div class="app-box-san"> | |||
<div class="zuo"> | |||
<div class="title nof" style="border: none"> | |||
<!-- <div class="text1" style="font-size: 14px;">顾问{{ activeName | abName }}排名(TOP10)</div> --> | |||
<div class="text1" style="font-size: 14px; height: 44px"> | |||
顾问排名(TOP10) | |||
</div> | |||
@@ -326,12 +297,6 @@ | |||
<el-radio-button label="1">接待时长</el-radio-button> | |||
<el-radio-button label="2">违禁次数</el-radio-button> | |||
</el-radio-group> | |||
<!-- <el-menu :default-active="activeName" background-color="#FFFFFF" active-text-color="#2671E2" mode="horizontal" @select="handleClick"> | |||
<el-menu-item style="font-size: 12px;" index="3">平均执行率</el-menu-item> | |||
<el-menu-item style="font-size: 12px;" index="0">接待量</el-menu-item> | |||
<el-menu-item style="font-size: 12px;" index="1">接待时长</el-menu-item> | |||
<el-menu-item style="font-size: 12px;" index="2">违禁次数</el-menu-item> | |||
</el-menu> --> | |||
</div> | |||
</div> | |||
<div | |||
@@ -362,32 +327,6 @@ | |||
</template> | |||
</div> | |||
<div v-if="activeName == '10'"> | |||
<!-- <div v-if="ceratelist.list.length != 0" style=" | |||
/* height: 360px; */ | |||
width: 94%; | |||
margin: 0 auto; | |||
margin-top: 15px; | |||
margin-bottom: 16px; | |||
"> | |||
<div class="jinbox" v-for="(item, i) in ceratelist.list" :key="i"> | |||
<div class="jinboxtit"> | |||
<span class="sequenceNum" :style="{ | |||
'background': i + 1 == 1 ? 'linear-gradient(180deg, #FFA395 0%, #F54D3F 100%)' : i + 1 == 2 ? 'linear-gradient(180deg, #FFBE70 0%, #FF981E 100%)' : i + 1 == 3 ? 'linear-gradient(180deg, #FFE683 0%, #FFCC00 100%)' : '#E5F0FF', | |||
'color': i + 1 == 1 ? '#FFF' : i + 1 == 2 ? '#FFF' : i + 1 == 3 ? '#FFF' : '#333', | |||
'box-shadow': i + 1 == 1 ? '0px 0px 6px 1px #F54D3F' : i + 1 == 2 ? '0px 0px 6px 1px #FF981E' : i + 1 == 3 ? '0px 0px 6px 1px #FFCC00' : '#E5F0FF', | |||
}">{{ i + 1 }}</span> | |||
<span class="name">{{ item.name }}</span> | |||
</div> | |||
<div class="jinbox-box"> | |||
<div class="boxbaifenbi" | |||
:style="{ 'background': i + 1 == 1 ? 'linear-gradient(270deg, #F88881 0%, #E6625B 100%)' : i + 1 == 2 ? 'linear-gradient(270deg, #FFC940 0%, #FF981E 100%)' : i + 1 == 3 ? 'linear-gradient(270deg, #FFE800 0%, #FFCC00 100%)' : 'inear-gradient(270deg, #7BB1FF 0%, #618FFF 100%)', 'width': item.zxl1 + '%' }"> | |||
</div> | |||
</div> | |||
<div class="jinboxbott"> | |||
{{ item.zxl || 0 }}{{ activeName | company }} | |||
</div> | |||
</div> | |||
</div> --> | |||
<div class="nulllist" v-if="ceratelist.list.length == 0"> | |||
<div class="imgboxc"> | |||
<img class="imgboxc-img" src="/img/nullnull.png" alt="" /> | |||
@@ -397,66 +336,6 @@ | |||
</div> | |||
<div v-else id="xxx" style="width: 100%; height: 400px"></div> | |||
</div> | |||
<!-- <div class="you"> | |||
<div class="title"> | |||
<div class="text1">系统访问排名(TOP10)</div> | |||
<div | |||
style="display: flex; justify-content: flex-end" | |||
class="text2" | |||
> | |||
<el-menu | |||
:default-active="activeIndex" | |||
mode="horizontal" | |||
@select="systemFrom" | |||
> | |||
<el-menu-item index="">全部</el-menu-item> | |||
<el-menu-item index="pig">PC</el-menu-item> | |||
<el-menu-item index="test">小程序</el-menu-item> | |||
</el-menu> | |||
</div> | |||
</div> | |||
<div class="hejisan"> | |||
<div class="sanbox1" style="width: 30%"> | |||
<div class="text1-1">访问合计</div> | |||
<div class="text1-2">{{ systemList.sum || 0 }}次</div> | |||
</div> | |||
<div class="sanbox1" style="width: 40%"> | |||
<div class="text1-1">人数</div> | |||
<div class="text1-2">{{ systemList.num || 0 }}人</div> | |||
</div> | |||
<div class="sanbox1" style="width: 30%"> | |||
<div class="text1-1">均值</div> | |||
<div class="text1-2">{{ systemList.avg || 0 }}次</div> | |||
</div> | |||
</div> | |||
<div | |||
v-if="systemList.list.length != 0" | |||
style=" | |||
height: 360px; | |||
width: 94%; | |||
margin: 0 auto; | |||
margin-top: 15px; | |||
margin-bottom: 16px; | |||
" | |||
> | |||
<div class="jinbox" v-for="(item, i) in systemList.list" :key="i"> | |||
<div class="jinboxtit">{{ item.name }}</div> | |||
<div class="jinbox-box"> | |||
<div | |||
class="boxbaifenbi" | |||
:style="'width:' + item.zxl1 + '%;'" | |||
></div> | |||
</div> | |||
<div class="jinboxbott">{{ item.zxl }}次</div> | |||
</div> | |||
</div> | |||
<div class="nulllist" v-if="systemList.list.length == 0"> | |||
<div class="imgboxc"> | |||
<img class="imgboxc-img" src="/img/nullnull.png" alt="" /> | |||
<div class="nulltext">暂无数据</div> | |||
</div> | |||
</div> | |||
</div> --> | |||
</div> | |||
<!-- 五 --> | |||
@@ -531,10 +410,8 @@ | |||
> | |||
<span class="name">{{ item.name }}</span> | |||
</el-tooltip> | |||
<!-- <span class="name">{{ item.name }}</span> --> | |||
</div> | |||
<div class="jinbox-box"> | |||
<!-- <div class="boxbaifenbi" :style="'width:' + item.zxl + '%;'"></div> --> | |||
<div | |||
class="boxbaifenbi" | |||
:style="{ | |||
@@ -1640,7 +1517,7 @@ export default { | |||
if (index == 0) { | |||
this.customtime = []; | |||
} | |||
// 近7天 | |||
if (index == 4) { | |||
let starTime = new Date().getTime() - 24 * 60 * 60 * 1000 * 7; | |||
let startDate = `${new Date(starTime).getFullYear()}-${ | |||
@@ -1653,7 +1530,7 @@ export default { | |||
this.customtime = [startDate, endDate]; | |||
} | |||
// 近30天 | |||
if (index == 6) { | |||
let starTime = new Date().getTime() - 24 * 60 * 60 * 1000 * 30; | |||
let startDate = `${new Date(starTime).getFullYear()}-${ | |||
@@ -194,7 +194,7 @@ | |||
<!-- 评分 --> | |||
<div class="content-right"> | |||
<el-row> | |||
<el-col :span="10"> | |||
<el-col :span="10" v-if="false"> | |||
<div style="display: flex; align-items: center"> | |||
<span style="width: 120px">话术名称</span> | |||
@@ -968,14 +968,14 @@ export default { | |||
}, | |||
// 评分保存 新增模板 | |||
saveRate(params) { | |||
if(!params.templateName) { | |||
// if(!params.templateName) { | |||
this.$message({ | |||
message: "请填写模板名称", | |||
type: "error", | |||
}); | |||
return | |||
} | |||
// this.$message({ | |||
// message: "请填写模板名称", | |||
// type: "error", | |||
// }); | |||
// return | |||
// } | |||
if (this.Templateid != "") { | |||
params.tempId = this.Templateid; | |||
} | |||
@@ -0,0 +1,773 @@ | |||
<template> | |||
<div class="box-center"> | |||
<div class="app-top"> | |||
<el-radio-group v-model="keyType" size="medium" @change="search"> | |||
<el-radio-button :label="0">需求挖掘</el-radio-button> | |||
<el-radio-button :label="1">销讲词</el-radio-button> | |||
<el-radio-button :label="2">客户标签</el-radio-button> | |||
<el-radio-button :label="3">违禁词</el-radio-button> | |||
</el-radio-group> | |||
<el-input size="small" clearable style="margin: 0 10px;width: 220px" v-model="value" placeholder="标签名称"></el-input> | |||
<el-select | |||
v-if="orgType==0" | |||
v-model="houseId" | |||
@change="houseChange" | |||
placeholder="请选择" | |||
filterable | |||
> | |||
<el-option | |||
v-for="item in houseList" | |||
:key="item.id" | |||
:label="item.propertyName" | |||
:value="item.id" | |||
> | |||
</el-option> | |||
</el-select> | |||
<el-button size="small" type="primary" @click="search()">筛选</el-button> | |||
<el-button size="small" type="text" @click="Emptycondition()">清空筛选条件</el-button> | |||
</div> | |||
<div class="app-box"> | |||
<el-table | |||
:data="tableData" | |||
stripe | |||
:load="loading" | |||
:header-cell-style="{background:'#F7F8FA',borderColor:'#E0E0E0',color:'#606775'}" | |||
style="width: 100%"> | |||
<el-table-column | |||
prop="level1Name" | |||
:label="keyType==3?'违禁词':'画像一级'" | |||
align="center"> | |||
</el-table-column> | |||
<el-table-column | |||
v-if="keyType!=3" | |||
prop="level2Name" | |||
label="画像二级" | |||
align="center"> | |||
</el-table-column> | |||
<el-table-column | |||
v-if="keyType!=3" | |||
prop="level3Name" | |||
:label="keyType==0?'挖掘话术':'画像三级'" | |||
align="center"> | |||
</el-table-column> | |||
<el-table-column | |||
prop="showFormatExpression" | |||
label="匹配模型" | |||
width="330" | |||
align="center"> | |||
<template slot-scope="scope"> | |||
<el-tooltip class="item" effect="dark" placement="top"> | |||
<div v-html="scope.row.showFormatExpression" slot="content" style="max-width: 530px;"></div> | |||
<div class="hidden-tooltip">{{scope.row.showFormatExpression}}</div> | |||
</el-tooltip> | |||
</template> | |||
</el-table-column> | |||
<el-table-column | |||
prop="distance" | |||
label="匹配距离" | |||
align="center"> | |||
</el-table-column> | |||
<el-table-column | |||
prop="updateUserName" | |||
label="最后修改人" | |||
align="center"> | |||
</el-table-column> | |||
<el-table-column | |||
prop="updateTime" | |||
label="最后修改时间" | |||
width="110" | |||
align="center"> | |||
</el-table-column> | |||
<el-table-column label="操作" width="140" fixed="right" align="center"> | |||
<template slot-scope="scope"> | |||
<el-button v-if="permissions.bianJiMoBan" type="text" @click="editFun(scope.row)">编辑</el-button> | |||
<el-button type="text" @click="deleteFun(scope.row)">删除</el-button> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<div class="block"> | |||
<div class="blockbox"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="pageNum" | |||
:page-sizes="[10, 20, 30, 40,50,100]" | |||
:page-size="pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
<el-dialog | |||
title="编辑模型" | |||
@open="openModel" | |||
:close-on-click-modal="false" | |||
:visible.sync="dialogVisible" | |||
> | |||
<matching-rules :key="timer" :innerVisible="innerVisible"></matching-rules> | |||
<el-form ref="form" size="mini" :inline="true" :model="form" label-position="right"> | |||
<el-form-item :label="keyType==0?'挖掘话术:':keyType==3?'违禁词:':'标签名称:'"> | |||
<div style="max-width:400px;min-width: 200px;">{{form.keywordsName}}</div> | |||
</el-form-item> | |||
<el-form-item label="after,near,answer 匹配距离:"> | |||
<el-input-number v-model="form.distance" controls-position="right" :min="0" :max="500"></el-input-number></el-input><span style="color:red;margin-left:10px">*请输入0~500内的整数</span> <el-button type="text" style="margin-left:30px" @click="innerVisible=true;timer=new Date().getTime()">规则说明</el-button> | |||
</el-form-item> | |||
<div contentEditable="true" | |||
@click="myeditorenter($event)" | |||
@keypress.enter="myeditorenter($event)" | |||
@blur="saveRange" | |||
@paste="onPaste" | |||
class="editDiv" | |||
id="huashuModel"> | |||
</div> | |||
<div v-if="keyType==0||dynamiclist.length">{{keyType==0?'匹配标签:':'需求挖掘匹配:'}}</div> | |||
<!-- <%-- keyType=0 需求挖掘--%> --> | |||
<div class="dynamicbox" v-if="keyType==0"> | |||
<div v-for="(item,index) in dynamiclist" :key="item" class="itemlist"> | |||
<el-select size="small" v-model="item.markid" @change="checkrepeat" placeholder="标签" clearable> | |||
<el-option v-for="(mark,i) in wajueList" :disabled="mark.disabled" :key="i" :label="mark.name" :value="mark.id"></el-option> | |||
</el-select> | |||
<div contentEditable="true" | |||
@click="myeditorenter($event)" | |||
@keypress.enter="myeditorenter($event)" | |||
@blur="saveRange" | |||
class="item-input" | |||
v-html="item.editValue" | |||
:id="'huashuModel'+index"></div> | |||
<el-button size="small" plain type="primary" @click="delItemFun(index)">删除</el-button> | |||
</div> | |||
</div> | |||
<div class="dynamicbox" v-else> | |||
<div v-for="item in dynamiclist" :key="item" class="itemlist"> | |||
<el-input size="small" disabled style="width: 220px" v-model="item.question"></el-input> | |||
<div class="item-input" style="pointer-events: none;" v-html="item.editValue"></div> | |||
</div> | |||
</div> | |||
<div> | |||
<el-button v-if="keyType==0" :disabled="dynamiclist.length==wajueList.length" @click="addItemFun" icon="el-icon-plus" type="primary" size="mini" style="width: 120px;margin:20px 0;"></el-button> | |||
</div> | |||
<el-form-item label="插入节点:"> | |||
<el-button size="mini" type="primary" style="margin-left:8px;" v-for="(item,index) in taglist" :key="index" @click="insertTag(item,index)">{{item.label}}</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<span slot="footer" class="dialog-footer"> | |||
<el-button @click="dialogVisible = false">取 消</el-button> | |||
<el-button type="primary" @click="saveFun">保 存</el-button> | |||
</span> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapGetters } from "vuex"; | |||
import matchingRules from "@/components/matchingRules/matchingRules.vue"; | |||
export default { | |||
components: { matchingRules }, | |||
data() { | |||
return { | |||
timer: 0, | |||
dynamiclist: [], | |||
taglist: [ | |||
{ | |||
label: "or (或)", | |||
value: "or", | |||
}, | |||
{ | |||
label: "near (临近)", | |||
value: "near", | |||
}, | |||
{ | |||
label: "after (后面)", | |||
value: "after", | |||
}, | |||
{ | |||
label: "and not (非)", | |||
value: "andnot", | |||
}, | |||
// { | |||
// label: 'answer (问题)', | |||
// value: 'answer' | |||
// }, | |||
], | |||
form: { | |||
keywordsName: "", | |||
id: "", | |||
keywordsId: "", | |||
distance: 10, | |||
originalExpression: "", | |||
}, | |||
innerVisible: false, | |||
innerVisible1: false, | |||
dialogVisible: false, | |||
value: "", | |||
keyType: 0, | |||
loading: false, | |||
currentPage: 1, | |||
tableData: [], | |||
type: "0", | |||
pageNum: 1, | |||
pageSize: 10, | |||
total: 0, | |||
huashu: "", | |||
wajueList: [], | |||
level: "", | |||
houseId: "", | |||
orgType: "", | |||
houseList: [], | |||
}; | |||
}, | |||
created() { | |||
this.houseId = localStorage.getItem("houseId"); | |||
this.orgType = localStorage.getItem("orgType"); | |||
this.orgType == 0 ? this.zkhousePage() : this.getorgCode(); | |||
}, | |||
computed: { | |||
...mapGetters(["permissions"]), | |||
}, | |||
methods: { | |||
// 获取项目列表 | |||
zkhousePage() { | |||
this.$api.api | |||
.findHouseByUser({ | |||
orgType: localStorage.getItem("orgType"), | |||
}) | |||
.then((res) => { | |||
this.houseList = res.data; | |||
this.houseId = res.data[0].id; | |||
this.getorgCode(); | |||
}); | |||
}, | |||
houseChange() { | |||
this.getorgCode(); | |||
}, | |||
// 校验是否已经选择过此标签 | |||
checkrepeat() { | |||
this.wajueList.forEach((item) => { | |||
item.disabled = false; | |||
}); | |||
this.wajueList.forEach((item) => { | |||
this.dynamiclist.forEach((obj) => { | |||
if (item.id == obj.markid) { | |||
item.disabled = true; | |||
} | |||
}); | |||
}); | |||
}, | |||
addItemFun() { | |||
this.dynamiclist.push({ | |||
editValue: "", //匹配模型正则表达式 | |||
markid: "", | |||
level: "", | |||
name: "", | |||
}); | |||
}, | |||
delItemFun(index) { | |||
this.wajueList.forEach((item) => { | |||
if (item.id == this.dynamiclist[index].markid) { | |||
item.disabled = false; | |||
} | |||
}); | |||
this.dynamiclist.splice(index, 1); | |||
document.getElementById("huashuModel").focus(); // 防止插入到外面,造成不可删除的操作 | |||
}, | |||
// 基于保存的光标插入内容 --用于失去焦点后再继续插入内容 | |||
insertContent(str) { | |||
let selection, | |||
range = window._range; // 当前光标位置对象 | |||
if (!window.getSelection) { | |||
range.pasteHTML(str); | |||
range.collapse(false); | |||
range.select(); | |||
} else { | |||
selection = window.getSelection | |||
? window.getSelection() | |||
: document.selection; | |||
range.collapse(false); | |||
let hasR = range.createContextualFragment(str); | |||
let hasR_lastChild = hasR.lastChild; | |||
while ( | |||
hasR_lastChild && | |||
hasR_lastChild.nodeName.toLowerCase() == "br" && | |||
hasR_lastChild.previousSibling && | |||
hasR_lastChild.previousSibling.nodeName.toLowerCase() == "br" | |||
) { | |||
let e = hasR_lastChild; | |||
hasR_lastChild = hasR_lastChild.previousSibling; | |||
hasR.removeChild(e); | |||
} | |||
range.insertNode(hasR); | |||
if (hasR_lastChild) { | |||
range.setEndAfter(hasR_lastChild); | |||
range.setStartAfter(hasR_lastChild); | |||
} | |||
selection.removeAllRanges(); | |||
selection.addRange(range); | |||
} | |||
}, | |||
// 失去焦点时保存光标位置,记录光标位置 | |||
saveRange: () => { | |||
let selection = window.getSelection | |||
? window.getSelection() | |||
: document.selection; | |||
if (!selection.rangeCount) return; | |||
let range = selection.createRange | |||
? selection.createRange() | |||
: selection.getRangeAt(0); | |||
window._range = range; | |||
}, | |||
// 回显模型数据,Dialog 的内容是懒渲染的,即在第一次被打开之前,传入的默认 slot 不会被渲染到 DOM 上,so在 open 事件回调中进行 | |||
openModel() { | |||
this.$nextTick(() => { | |||
let huashuModel = document.getElementById("huashuModel"); | |||
huashuModel.innerHTML = this.form.originalExpression; | |||
}); | |||
}, | |||
//格式化粘贴文本方法 | |||
onPaste(event) { | |||
// var e = event || window.event | |||
// // 阻止默认粘贴 | |||
// e.preventDefault(); | |||
// // 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
// // clipboardData的getData(fomat) 从剪贴板获取指定格式的数据 | |||
// var text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('在这里输入文本'); | |||
// //清除回车 | |||
// text = text.replace(/\[\d+\]|\n|\r/ig,"") | |||
// // 插入 | |||
// document.execCommand("insertText", false, text); | |||
let e = event || window.event; | |||
let types = event.clipboardData.types; | |||
// 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
let flag = false; | |||
if (types && types.length > 0) { | |||
types.forEach((ele) => { | |||
if (ele == "Files") { | |||
flag = true; | |||
} | |||
}); | |||
} | |||
if (flag) { | |||
event.preventDefault(); | |||
} | |||
}, | |||
myeditorenter(e) { | |||
e.preventDefault(); | |||
}, | |||
// 插入节点 | |||
insertHtmlAtCaret(html) { | |||
document.getElementById("huashuModel").focus(); | |||
var sel, range; | |||
if (window.getSelection) { | |||
// IE9 and non-IE | |||
sel = window.getSelection(); | |||
if (sel.getRangeAt && sel.rangeCount) { | |||
range = sel.getRangeAt(0); | |||
range.deleteContents(); | |||
// Range.createContextualFragment() would be useful here but is | |||
// non-standard and not supported in all browsers (IE9, for one) | |||
var el = document.createElement("div"); | |||
el.innerHTML = html; | |||
var frag = document.createDocumentFragment(), | |||
node, | |||
lastNode; | |||
while ((node = el.firstChild)) { | |||
lastNode = frag.appendChild(node); | |||
} | |||
range.insertNode(frag); | |||
// Preserve the selection | |||
if (lastNode) { | |||
range = range.cloneRange(); | |||
range.setStartAfter(lastNode); | |||
range.collapse(true); | |||
sel.removeAllRanges(); | |||
sel.addRange(range); | |||
} | |||
} | |||
} else if (document.selection && document.selection.type != "Control") { | |||
// IE < 9 | |||
document.selection.createRange().pasteHTML(html); | |||
} | |||
}, | |||
// 拿问题获取所在的标签数据 | |||
findKeywordsById(keywordsId) { | |||
axios({ | |||
url: `/autoSR/zk/keywords/findKeywordsById`, | |||
method: "get", | |||
params: { | |||
houseId: this.houseId, | |||
keywordsId: keywordsId, | |||
level: 1, | |||
}, | |||
}).then((res) => { | |||
if (res.code == 0) { | |||
// console.log(res.data) | |||
this.wajueList = res.data; | |||
if (this.wajueList && this.wajueList.length) { | |||
this.wajueList.forEach((item) => { | |||
item.disabled = false; | |||
}); | |||
this.wajueList.forEach((item) => { | |||
this.dynamiclist.forEach((obj) => { | |||
if (item.id == obj.markid) { | |||
item.disabled = true; | |||
} | |||
}); | |||
}); | |||
} | |||
} | |||
}); | |||
}, | |||
// 插入节点 | |||
insertTag(item, index) { | |||
if (index == 4) { | |||
// answer | |||
this.huashu = ""; | |||
this.innerVisible1 = true; | |||
} else { | |||
if (window._range) { | |||
this.insertContent( | |||
"<span contentEditable='false' style='color:red'>" + | |||
item.value + | |||
"</span><text> </text>" | |||
); | |||
} else { | |||
this.insertHtmlAtCaret( | |||
"<span contentEditable='false' style='color:red'>" + | |||
item.value + | |||
"</span><text> </text>" | |||
); | |||
} | |||
} | |||
}, | |||
// 处理标签,删除不需要的标签格式 | |||
delMark(str) { | |||
const hasStr = (str) => { | |||
let index = str.indexOf("<"); | |||
let index1 = str.indexOf(">"); | |||
if (index > 0 && index1 > 0) { | |||
let replaceStr = str.substring(index, index1 + 1); | |||
str = str.replace(replaceStr, ""); | |||
hasStr(str); | |||
} | |||
}; | |||
hasStr(str); | |||
}, | |||
// 确认插入选择的话术 | |||
clickOK() { | |||
this.innerVisible1 = false; | |||
if (!this.huashu) { | |||
this.$message.error("请选择话术"); | |||
return; | |||
} | |||
this.insertContent( | |||
"<text>" + | |||
this.huashu + | |||
"</text><span contentEditable='false' style='color:red'>answer</span><text> </text>" | |||
); | |||
}, | |||
search() { | |||
this.pageNum = 1; | |||
this.getorgCode(); | |||
}, | |||
//点击编辑按钮 | |||
editFun(item) { | |||
this.dialogVisible = true; | |||
this.form.id = item.id; | |||
if (this.keyType == 0) { | |||
// 挖掘话术类型 | |||
// 回显标签模型数据 | |||
if (item.answerList && item.answerList.length) { | |||
this.dynamiclist = item.answerList.map((obj) => { | |||
return { | |||
id: obj.id, | |||
mark: obj.level3Name ? obj.level3Name : obj.level2Name, | |||
level: obj.level3Id ? 3 : 2, | |||
editValue: obj.originalExpression, | |||
markid: obj.level3Id ? obj.level3Id : obj.level2Id, | |||
}; | |||
}); | |||
// console.log(this.dynamiclist) | |||
} else { | |||
this.dynamiclist = []; | |||
} | |||
this.form.keywordsName = item.level3Name; | |||
this.form.distance = item.distance || 10; | |||
this.form.originalExpression = | |||
item.originalExpression || item.level3Name; | |||
this.level = item.level2Id ? 2 : 1; | |||
this.questionId = item.questionId; | |||
this.form.keywordsId = item.level2Id ? item.level2Id : item.level1Id; | |||
this.findKeywordsById(item.level1Id); // 获取标签下拉数据 | |||
} else if (this.keyType == 3) { | |||
// 违禁词 | |||
this.form.keywordsName = item.level1Name; | |||
this.level = 1; | |||
this.form.distance = item.distance || 10; | |||
this.form.originalExpression = | |||
item.originalExpression || item.level1Name; | |||
this.dynamiclist = []; | |||
} else { | |||
this.form.keywordsId = item.level3Id ? item.level3Id : item.level2Id; | |||
this.level = item.level3Id ? 3 : 2; | |||
this.form.keywordsName = item.level3Name || item.level2Name; | |||
this.form.distance = item.distance || 10; | |||
this.form.originalExpression = | |||
item.originalExpression || item.level3Name || item.level2Name; | |||
if (item.answerList && item.answerList.length) { | |||
this.dynamiclist = item.answerList.map((obj) => { | |||
return { | |||
question: obj.question, | |||
editValue: obj.originalExpression, | |||
}; | |||
}); | |||
} else { | |||
this.dynamiclist = []; | |||
} | |||
} | |||
}, | |||
// 删除列表 | |||
deleteFun(item) { | |||
this.$alert(item.keywordsName, "确定删除该条数据吗", { | |||
confirmButtonText: "确定", | |||
callback: (action) => { | |||
axios({ | |||
url: `/autoSR/zk/keymodel/delKeywordsModel`, | |||
method: "get", | |||
params: { | |||
id: item.id, | |||
houseId: this.houseId, | |||
}, | |||
}) | |||
.then((data) => { | |||
if (data.code == 0) { | |||
this.getorgCode(); | |||
} | |||
}) | |||
.catch((e) => {}); | |||
}, | |||
}); | |||
}, | |||
// 处理模型 关键词加#号 | |||
replaceFun(str) { | |||
let temp = str; | |||
temp = temp.replace(/<text>\ \;<\/text>/g, ""); | |||
temp = temp.replace(/\ \;/g, ""); | |||
temp = temp.replace(/<text>/g, ""); | |||
temp = temp.replace(/<\/text>/g, ""); | |||
temp = temp.replace( | |||
/<span contenteditable="false" style="color:red">/g, | |||
" #" | |||
); // 后台返回是这样的,变了,需要也处理一下 | |||
temp = temp.replace( | |||
/<span style="color:red" contenteditable="false">/g, | |||
" #" | |||
); | |||
temp = temp.replace(/<\/br>/g, ""); | |||
temp = temp.replace(/<br>/g, ""); | |||
temp = temp.replace(/<\/span>/g, "#"); | |||
// console.log('处理前temp',temp); | |||
this.delMark(temp); | |||
// console.log(temp); | |||
return temp; | |||
}, | |||
//修改保存标签模型 | |||
saveFun() { | |||
if (this.cansave) return; // 防止多次点击 | |||
this.cansave = true; | |||
let text = document.getElementById("huashuModel"); | |||
let answerList = []; | |||
// console.log(text.innerHTML); | |||
// console.log(text.innerText); | |||
let temp = text.innerHTML; | |||
if (this.form.distance == "") { | |||
this.$message.error("请输入距离"); | |||
return; | |||
} | |||
if (text.innerText == "") { | |||
this.$message.error("请输入标签模型"); | |||
return; | |||
} | |||
if (this.keyType == 0) { | |||
for (var i = 0; i < this.dynamiclist.length; i++) { | |||
// 使用for循环判断可以跳出循环 | |||
if (!this.dynamiclist[i].markid) { | |||
this.$message.error("请完善要选择的标签"); | |||
return; | |||
} | |||
this.wajueList.map((item1) => { | |||
if (item1.id == this.dynamiclist[i].markid) { | |||
this.dynamiclist[i].level = item1.level; | |||
this.dynamiclist[i].name = item1.name; | |||
} | |||
}); | |||
let huashuModel = document.getElementById("huashuModel" + i); | |||
if (huashuModel.innerText == "") { | |||
this.$message.error("请完善选择的标签模型"); | |||
return; | |||
} | |||
this.dynamiclist[i].editValue = huashuModel.innerHTML; | |||
this.dynamiclist[i].editText = huashuModel.innerText; | |||
} | |||
answerList = this.dynamiclist.map((item) => { | |||
return { | |||
keyType: 2, | |||
id: item.id || null, | |||
level: item.level, | |||
keywordsId: item.markid, | |||
showFormatExpression: item.editText, //文本形式 | |||
formatExpression: this.replaceFun(item.editValue), // 问题表达式,关键词加#号 | |||
original: item.editValue, // html==带span标签 | |||
}; | |||
}); | |||
} | |||
axios({ | |||
url: `/autoSR/zk/keymodel/updateKeywordsModel`, | |||
method: "post", | |||
data: { | |||
id: this.form.id, | |||
questionId: this.keyType == 0 ? this.questionId : "", | |||
houseId: this.houseId, | |||
keyType: this.keyType, | |||
level: this.level, | |||
keywordsId: this.form.keywordsId, | |||
keywordsName: this.form.keywordsName, | |||
formatExpression: this.replaceFun(temp), // 问题表达式,关键词加#号 | |||
original: temp, // html==带span标签 | |||
answerList: answerList, | |||
showFormatExpression: text.innerText, | |||
distance: this.form.distance, // 距离 | |||
}, | |||
}) | |||
.then((res) => { | |||
this.cansave = false; | |||
this.dialogVisible = false; | |||
if (res.code == 0) { | |||
this.$message.success(res.data); | |||
this.getorgCode(); | |||
} else { | |||
this.$message.error(res.msg); | |||
} | |||
}) | |||
.catch((e) => { | |||
this.cansave = false; | |||
this.dialogVisible = false; | |||
}); | |||
}, | |||
//清空筛选条件 | |||
Emptycondition() { | |||
this.value = ""; | |||
this.keyType = 0; | |||
this.pageNum = 1; | |||
this.getorgCode(); | |||
}, | |||
//初始化 | |||
getorgCode() { | |||
this.loading = true; | |||
this.tableData = []; | |||
axios({ | |||
url: `/autoSR/zk/keymodel/findKeywordsModel`, | |||
method: "get", | |||
params: { | |||
houseId: this.houseId, | |||
current: this.pageNum, | |||
size: this.pageSize, | |||
keywordsName: this.value, | |||
keyType: this.keyType, | |||
}, | |||
}) | |||
.then((res) => { | |||
this.loading = false; | |||
if (res.code == 0) { | |||
this.tableData = res.data.records || []; | |||
this.total = res.data.total; | |||
} | |||
}) | |||
.catch((e) => { | |||
this.loading = false; | |||
}); | |||
}, | |||
handleSizeChange(val) { | |||
console.log("每页条" + val); | |||
this.pageSize = val; | |||
this.getorgCode(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log("当前页" + val); | |||
this.pageNum = val; | |||
this.getorgCode(); | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style lang="scss" scoped > | |||
.box-center { | |||
width: 100%; | |||
padding: 5px 15px 40px; | |||
min-width: 1000px; | |||
} | |||
.app-top { | |||
margin-bottom: 20px; | |||
width: 100%; | |||
background: #ffffff; | |||
box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.04); | |||
border-radius: 4px; | |||
padding: 15px; | |||
} | |||
.block { | |||
width: 100%; | |||
margin-top: 5px; | |||
display: flex; | |||
} | |||
.blockbox { | |||
margin-left: auto; | |||
} | |||
.editDiv { | |||
width: 100%; | |||
min-height: 60px; | |||
max-height: 120px; | |||
overflow: auto; | |||
margin-bottom: 10px; | |||
padding: 15px; | |||
outline: none; | |||
border: 1px solid #409eff; | |||
border-radius: 10px; | |||
} | |||
.hidden-tooltip { | |||
width: 330px; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
white-space: nowrap; | |||
position: relative; | |||
} | |||
.itemlist { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
margin: 20px 0; | |||
} | |||
.item-input { | |||
width: 100%; | |||
padding: 4px 10px; | |||
outline: none; | |||
border: 1px solid #409eff; | |||
border-radius: 4px; | |||
overflow: auto; | |||
line-height: 24px; | |||
min-height: 24px; | |||
max-height: 100px; | |||
margin: 0 10px; | |||
} | |||
.el-dialog { | |||
width: 800px; | |||
} | |||
.el-dialog__body { | |||
max-height: 400px; | |||
overflow: auto; | |||
} | |||
</style> | |||
@@ -0,0 +1,836 @@ | |||
<template> | |||
<div class="box-center"> | |||
<div class="app-top"> | |||
<div class="control-tab"> | |||
<el-radio-group v-model="type" size="medium" @change="changeType"> | |||
<el-radio-button :label="1">待处理</el-radio-button> | |||
<el-radio-button :label="0">已处理</el-radio-button> | |||
</el-radio-group> | |||
</div> | |||
<div class="app-titel" style="margin-top: 5px"> | |||
<div class="label">更新时间:</div> | |||
<el-date-picker | |||
style="width: 270px" | |||
@change="confirmtime" | |||
v-model="searchForm.customtime" | |||
type="daterange" | |||
range-separator="-" | |||
value-format="yyyy-MM-dd" | |||
start-placeholder="开始日期" | |||
end-placeholder="结束日期" | |||
></el-date-picker> | |||
<div class="label"> | |||
名称: | |||
<el-input | |||
placeholder="名称" | |||
v-model="searchForm.name" | |||
style="width: 140px" | |||
></el-input> | |||
</div> | |||
<div class="label" v-if="type == 0"> | |||
处理人: | |||
<el-input | |||
placeholder="处理人" | |||
v-model="searchForm.updateUserName" | |||
style="width: 140px" | |||
></el-input> | |||
</div> | |||
<div class="label"> | |||
项目名称: | |||
<el-input | |||
placeholder="项目名称" | |||
v-model="searchForm.houseName" | |||
style="width: 140px" | |||
></el-input> | |||
</div> | |||
<div style="margin-left: 20px"> | |||
<el-button @click="searchFun" type="primary">筛选</el-button> | |||
</div> | |||
</div> | |||
</div> | |||
<el-table | |||
:data="tableData" | |||
stripe | |||
:header-cell-style="{ | |||
background: '#F7F8FA', | |||
borderColor: '#E0E0E0', | |||
color: '#606775', | |||
}" | |||
style="width: 100%; margin-top: 20px" | |||
> | |||
<el-table-column prop="createTime" label="更新时间" align="center"> | |||
</el-table-column> | |||
<el-table-column prop="type" label="类型" align="center"> | |||
<template slot-scope="scope"> | |||
<!-- 0需求挖掘 1销讲词 2客户标签 3违禁 --> | |||
<span v-if="scope.row.type == 1">销讲话术</span> | |||
<span v-if="scope.row.type == 2">客户标签</span> | |||
<span v-if="scope.row.type == 0">挖掘话术</span> | |||
<span v-if="scope.row.type == 3">违禁词</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="level1Name" label="一级分类" align="center"> | |||
</el-table-column> | |||
<el-table-column prop="name" label="名称" align="center"> | |||
</el-table-column> | |||
<el-table-column prop="houseName" label="项目" align="center"> | |||
</el-table-column> | |||
<el-table-column prop="updateTime" label="处理时间" align="center" v-if="type == 0" > | |||
</el-table-column> | |||
<el-table-column prop="updateUserName" | |||
label="处理人" v-if="type == 0" align="center" > | |||
</el-table-column> | |||
<el-table-column label="操作" align="center"> | |||
<template slot-scope="scope"> | |||
<div v-if="permissions.piPeiMoXing" style="color: #2671e2; cursor: pointer" @click="editFun(scope.row)"> | |||
匹配模型 | |||
</div> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
<div class="block"> | |||
<div class="blockbox"> | |||
<el-pagination | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
:current-page="pageNum" | |||
:page-sizes="[10, 20, 30, 40, 50, 100]" | |||
:page-size="pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="total" | |||
> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
<el-dialog | |||
title="编辑模型" | |||
@open="openModel" | |||
:close-on-click-modal="false" | |||
:visible.sync="dialogVisible" | |||
> | |||
<matching-rules :key="timer" :innerVisible="innerVisible"></matching-rules> | |||
<el-form ref="form" size="mini" :inline="true" :model="form" label-position="right"> | |||
<el-form-item :label="keyType==0?'挖掘话术:':'标签名称:'"> | |||
<div style="max-width:400px;min-width: 200px;font-weight: bold">{{form.keywordsName}}</div> | |||
</el-form-item> | |||
<el-form-item label="场景描述:" > | |||
<div v-if="form.sceneDesc" style="width:500px;border: 1px dashed #ccc;padding:5px 10px;line-height: 25px"> {{form.sceneDesc}}</div> | |||
<div v-else>暂无描述</div> | |||
</el-form-item> | |||
<el-form-item label="after,near,answer 匹配距离:"> | |||
<el-input-number v-model="form.distance" controls-position="right" :min="0" :max="500"></el-input-number><span style="color:red;margin-left:10px">*请输入0~500内的整数</span> <el-button type="text" style="margin-left:30px" @click="innerVisible=true;timer=new Date().getTime()">规则说明</el-button> | |||
</el-form-item> | |||
<div contentEditable="true" | |||
@click="myeditorenter($event)" | |||
@keypress.enter="myeditorenter($event)" | |||
@blur="saveRange" | |||
class="editDiv" | |||
id="huashuModel"> | |||
</div> | |||
<div v-if="keyType==0||dynamiclist.length">{{keyType==0?'匹配标签:':'需求挖掘匹配:'}}</div> | |||
<!-- keyType 0需求挖掘 1销讲词 2客户标签 3违禁 --> | |||
<div class="dynamicbox" v-if="keyType==0"> | |||
<div v-for="(item,index) in dynamiclist" :key="item" class="itemlist"> | |||
<el-select size="small" v-model="item.markid" @change="checkrepeat" placeholder="标签" clearable> | |||
<el-option v-for="(mark,i) in wajueList" :disabled="mark.disabled" :key="i" :label="mark.name" :value="mark.id"></el-option> | |||
</el-select> | |||
<div contentEditable="true" | |||
@click="myeditorenter($event)" | |||
@keypress.enter="myeditorenter($event)" | |||
@blur="saveRange" | |||
class="item-input" | |||
v-html="item.editValue" | |||
:id="'huashuModel'+index"></div> | |||
<el-button size="small" type="primary" @click="delItemFun(index)">删除</el-button> | |||
</div> | |||
</div> | |||
<div class="dynamicbox" v-else> | |||
<div v-for="item in dynamiclist" :key="item" class="itemlist"> | |||
<el-input size="small" disabled style="width: 220px" v-model="item.question"></el-input> | |||
<div class="item-input" style="pointer-events: none;" v-html="item.editValue"></div> | |||
</div> | |||
</div> | |||
<div> | |||
<el-button :disabled="dynamiclist.length==wajueList.length" v-if="keyType==0" @click="addItemFun" icon="el-icon-plus" type="primary" size="mini" style="width: 120px;margin:20px 0;"></el-button> | |||
</div> | |||
<el-form-item label="插入节点:"> | |||
<el-button size="mini" type="primary" style="margin-left:8px;" v-for="(item,index) in taglist" :key="index" @click="insertTag(item,index)">{{item.label}}</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<span slot="footer" class="dialog-footer"> | |||
<el-button @click="dialogVisible = false">取 消</el-button> | |||
<el-button type="primary" @click="saveFun">保 存</el-button> | |||
</span> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapGetters } from "vuex"; | |||
import matchingRules from "@/components/matchingRules/matchingRules.vue"; | |||
export default { | |||
components: { matchingRules }, | |||
data() { | |||
return { | |||
huashu: "", | |||
wajueList: [], | |||
level: "", | |||
innerVisible: false, | |||
dialogVisible: false, | |||
dynamiclist: [], | |||
taglist: [ | |||
{ | |||
label: "or (或)", | |||
value: "or", | |||
}, | |||
{ | |||
label: "near (临近)", | |||
value: "near", | |||
}, | |||
{ | |||
label: "after (后面)", | |||
value: "after", | |||
}, | |||
{ | |||
label: "and not (非)", | |||
value: "andnot", | |||
}, | |||
// { | |||
// label: '~ (至)', | |||
// value: '~' | |||
// }, | |||
], | |||
form: { | |||
keywordsName: "", | |||
id: "", | |||
keywordsId: "", | |||
distance: 10, | |||
sceneDesc: "", | |||
originalExpression: "", | |||
}, | |||
searchForm: { | |||
updateUserName: "", | |||
houseName: "", | |||
name: "", | |||
customtime: [], | |||
startTime: "", //搜索开始时间 | |||
endTime: "", //搜索结束时间 | |||
}, | |||
tableData: [], | |||
type: 1, | |||
keyType: "", | |||
pageSize: 10, | |||
total: 0, | |||
pageNum: 1, | |||
houseId: '', | |||
currentHouseId: "", | |||
}; | |||
}, | |||
computed: { | |||
...mapGetters(["permissions"]), | |||
}, | |||
created(){ | |||
this.houseId=localStorage.getItem("houseId"); | |||
this.gettableList(); | |||
// this.orgType = localStorage.getItem("orgType") | |||
// this.orgType==0?this.zkhousePage():this.gettableList() | |||
}, | |||
methods: { | |||
// 获取项目列表 | |||
// zkhousePage() { | |||
// this.$api.api.findHouseByUser({ | |||
// orgType: localStorage.getItem("orgType"), | |||
// }).then((res) => { | |||
// this.houseList = res.data; | |||
// this.houseId = res.data[0].id; | |||
// this.gettableList(); | |||
// }); | |||
// }, | |||
houseChange(){ | |||
this.gettableList() | |||
}, | |||
// keytype =0,获取需求挖掘类型的数据回显接口 | |||
wajuehuixian() { | |||
// 获取模型数据回显 | |||
axios({ | |||
url: `/autoSR/zk/keymodel/findById`, | |||
method: 'get', | |||
params: { | |||
houseId: this.currentHouseId, | |||
level: this.level, | |||
keyType: 0, | |||
questionId: this.questionId, | |||
keywordsId: this.form.keywordsId | |||
} | |||
}).then((res) => { | |||
this.dialogVisible = true; | |||
if (res.code== 0) { | |||
let obj = res.data; | |||
if (obj != null) { | |||
this.form.distance = obj.distance || 10; | |||
this.form.originalExpression = obj.originalExpression; | |||
this.form.id = obj.id; | |||
this.form.sceneDesc = obj.desc || ""; | |||
// 回显标签模型数据 | |||
if (obj.answerList && obj.answerList.length) { | |||
this.dynamiclist = obj.answerList.map((obj1) => { | |||
return { | |||
id: obj1.id, | |||
mark: obj1.name, | |||
level: obj1.level3Id ? 3 : 2, | |||
editValue: obj1.originalExpression, | |||
markid: obj1.level3Id ? obj1.level3Id : obj1.level2Id, | |||
}; | |||
}); | |||
this.wajueList.forEach((item) => { | |||
this.dynamiclist.forEach((obj) => { | |||
if (item.id == obj.markid) { | |||
item.disabled = true; | |||
} | |||
}); | |||
}); | |||
// console.log(this.dynamiclist) | |||
} else { | |||
this.dynamiclist = []; | |||
} | |||
} else { | |||
this.form.distance = 10; | |||
this.form.originalExpression = ""; | |||
this.form.id = ""; | |||
this.form.sceneDesc = ""; | |||
this.dynamiclist = []; | |||
} | |||
} else { | |||
this.form.sceneDesc = ""; | |||
this.form.distance = 10; | |||
this.form.originalExpression = data.name; | |||
} | |||
this.$nextTick(() => { | |||
let huashuModel = document.getElementById("huashuModel"); | |||
huashuModel.innerHTML = this.form.originalExpression; | |||
}); | |||
}) | |||
.catch((e) => { | |||
this.dialogVisible = true; | |||
}); | |||
}, | |||
otherhuixian(type) { | |||
// 获取模型数据回显 | |||
axios({ | |||
url: `/autoSR/zk/keymodel/findById`, | |||
method: 'get', | |||
params: { | |||
houseId: this.currentHouseId, | |||
level: type==3?1:this.level, | |||
keyType: type, | |||
keywordsId: this.form.keywordsId | |||
} | |||
}).then((res) => { | |||
this.dialogVisible = true; | |||
if (res.code == 0) { | |||
let obj = res.data; | |||
if (obj != null) { | |||
this.form.distance = obj.distance || 10; | |||
this.form.originalExpression = obj.originalExpression || ""; | |||
this.form.id = obj.id || ""; | |||
this.form.sceneDesc = obj.desc || ""; | |||
// 回显标签模型数据 | |||
if (obj.answerList && obj.answerList.length) { | |||
this.dynamiclist = obj.answerList.map((cont) => { | |||
return { | |||
question: cont.question, | |||
editValue: cont.originalExpression, | |||
}; | |||
}); | |||
// console.log(this.dynamiclist); | |||
} else { | |||
this.dynamiclist = []; | |||
} | |||
} else { | |||
this.form.distance = 10; | |||
this.form.originalExpression = ""; | |||
this.form.id = ""; | |||
this.form.sceneDesc = ""; | |||
} | |||
} else { | |||
this.form.distance = 10; | |||
this.form.originalExpression = ""; | |||
this.form.sceneDesc = ""; | |||
} | |||
this.$nextTick(() => { | |||
let huashuModel = document.getElementById("huashuModel"); | |||
huashuModel.innerHTML = this.form.originalExpression; | |||
}); | |||
}) | |||
.catch((e) => { | |||
this.dialogVisible = true; | |||
}); | |||
}, | |||
//点击编辑按钮 | |||
async editFun(item) { | |||
this.keyType = item.type; | |||
this.todoId = item.id; | |||
this.level = item.level; | |||
this.form.keywordsId = item.keywordsId; | |||
this.currentHouseId = item.houseId; | |||
this.form.distance = item.distance || 10; | |||
let level1Id = item.level1; | |||
this.form.keywordsName = item.name; | |||
await this.findKeywordsById(level1Id); // 获取标签下拉数据 | |||
if (item.type == 0) { | |||
// 挖掘话术类型 | |||
this.questionId = item.wordId; | |||
this.wajuehuixian(level1Id); | |||
} else { | |||
this.otherhuixian(item.type); | |||
} | |||
}, | |||
// 处理标签,删除不需要的标签格式 | |||
delMark(str) { | |||
const hasStr = (str) => { | |||
let index = str.indexOf("<"); | |||
let index1 = str.indexOf(">"); | |||
if (index > 0 && index1 > 0) { | |||
let replaceStr = str.substring(index, index1 + 1); | |||
str = str.replace(replaceStr, ""); | |||
hasStr(str); | |||
} | |||
}; | |||
hasStr(str); | |||
}, | |||
// 处理模型 关键词加#号 | |||
replaceFun(str) { | |||
let temp = str; | |||
temp = temp.replace(/<text>\ \;<\/text>/g, ""); | |||
temp = temp.replace(/\ \;/g, ""); | |||
temp = temp.replace(/<text>/g, ""); | |||
temp = temp.replace(/<\/text>/g, ""); | |||
temp = temp.replace(/<span contenteditable="false" style="color:red">/g, " #"); // 后台返回是这样的,变了,需要也处理一下 | |||
temp = temp.replace(/<span style="color:red" contenteditable="false">/g," #"); | |||
temp = temp.replace(/<\/span>/g, "#"); | |||
temp = temp.replace(/<\/br>/g,'') | |||
temp = temp.replace(/<br>/g,'') | |||
// console.log(temp); | |||
// console.log('截取前',temp); | |||
this.delMark(temp); | |||
return temp; | |||
}, | |||
//修改保存标签模型 | |||
saveFun() { | |||
if (this.cansave) return; // 防止多次点击 | |||
this.cansave = true; | |||
let text = document.getElementById("huashuModel"); | |||
let answerList = []; | |||
// console.log(text.innerHTML); | |||
// console.log(text.innerText); | |||
let temp = text.innerHTML; | |||
if (this.form.distance == "") { | |||
this.$message.error("请输入距离"); | |||
return; | |||
} | |||
if (text.innerText == "") { | |||
this.$message.error("请输入标签模型"); | |||
return; | |||
} | |||
if (this.keyType == 0) { | |||
for (var i = 0; i < this.dynamiclist.length; i++) { | |||
if (!this.dynamiclist[i].markid) { | |||
this.$message.error("请完善要选择的标签"); | |||
return; | |||
} | |||
this.wajueList.map((item1) => { | |||
if (item1.id == this.dynamiclist[i].markid) { | |||
this.dynamiclist[i].level = item1.level; | |||
this.dynamiclist[i].name = item1.name; | |||
} | |||
}); | |||
let huashuModel = document.getElementById("huashuModel" + i); | |||
if (huashuModel.innerText == "") { | |||
this.$message.error("请完善选择的标签模型"); | |||
return; | |||
} | |||
this.dynamiclist[i].editValue = huashuModel.innerHTML; | |||
this.dynamiclist[i].editText = huashuModel.innerText; | |||
} | |||
answerList = this.dynamiclist.map((item) => { | |||
return { | |||
keyType: 2, | |||
id: item.id || null, | |||
level: item.level, | |||
keywordsId: item.markid, | |||
showFormatExpression: item.editText, //文本形式 | |||
formatExpression: this.replaceFun(item.editValue), // 问题表达式,关键词加#号 | |||
original: item.editValue, // html==带span标签 | |||
}; | |||
}); | |||
} | |||
this.$api.api | |||
.updateKeywordsModel({ | |||
id: this.form.id, | |||
questionId: this.keyType == 0 ? this.questionId : "", | |||
houseId: this.currentHouseId, | |||
keyType: this.keyType, | |||
level: this.keyType == 3 ? 1 : this.level, | |||
todoId: this.todoId, | |||
keywordsId: this.form.keywordsId, | |||
keywordsName: this.form.keywordsName, | |||
formatExpression: this.replaceFun(temp), // 问题表达式,关键词加#号 | |||
original: temp, // html==带span标签 | |||
answerList: answerList, | |||
showFormatExpression: text.innerText, | |||
}) | |||
.then((res) => { | |||
this.cansave = false; | |||
this.dialogVisible = false; | |||
if (res.code == 0) { | |||
this.$message.success(res.data); | |||
this.gettableList(); | |||
} else { | |||
this.$message.error(res.msg); | |||
} | |||
}) | |||
.catch((e) => { | |||
this.cansave = false; | |||
this.dialogVisible = false; | |||
}); | |||
}, | |||
// 校验是否已经选择过此标签 | |||
checkrepeat() { | |||
this.wajueList.forEach((item) => { | |||
item.disabled = false; | |||
}); | |||
this.wajueList.forEach((item) => { | |||
this.dynamiclist.forEach((obj) => { | |||
if (item.id == obj.markid) { | |||
item.disabled = true; | |||
} | |||
}); | |||
}); | |||
}, | |||
addItemFun() { | |||
this.dynamiclist.push({ | |||
editValue: "", //匹配模型正则表达式 | |||
markid: "", | |||
level: "", | |||
name: "", | |||
}); | |||
}, | |||
delItemFun(index) { | |||
this.wajueList.forEach((item) => { | |||
if (item.id == this.dynamiclist[index].markid) { | |||
item.disabled = false; | |||
} | |||
}); | |||
this.dynamiclist.splice(index, 1); | |||
document.getElementById("huashuModel").focus(); | |||
}, | |||
// 基于保存的光标插入内容 --用于失去焦点后再继续插入内容 | |||
insertContent(str) { | |||
let selection, | |||
range = window._range; // 当前光标位置对象 | |||
if (!window.getSelection) { | |||
range.pasteHTML(str); | |||
range.collapse(false); | |||
range.select(); | |||
} else { | |||
selection = window.getSelection | |||
? window.getSelection() | |||
: document.selection; | |||
range.collapse(false); | |||
let hasR = range.createContextualFragment(str); | |||
let hasR_lastChild = hasR.lastChild; | |||
while ( | |||
hasR_lastChild && | |||
hasR_lastChild.nodeName.toLowerCase() == "br" && | |||
hasR_lastChild.previousSibling && | |||
hasR_lastChild.previousSibling.nodeName.toLowerCase() == "br" | |||
) { | |||
let e = hasR_lastChild; | |||
hasR_lastChild = hasR_lastChild.previousSibling; | |||
hasR.removeChild(e); | |||
} | |||
range.insertNode(hasR); | |||
if (hasR_lastChild) { | |||
range.setEndAfter(hasR_lastChild); | |||
range.setStartAfter(hasR_lastChild); | |||
} | |||
selection.removeAllRanges(); | |||
selection.addRange(range); | |||
} | |||
}, | |||
// 失去焦点时保存光标位置,记录光标位置 | |||
saveRange: () => { | |||
let selection = window.getSelection | |||
? window.getSelection() | |||
: document.selection; | |||
if (!selection.rangeCount) return; | |||
let range = selection.createRange | |||
? selection.createRange() | |||
: selection.getRangeAt(0); | |||
window._range = range; | |||
}, | |||
// 回显模型数据,Dialog 的内容是懒渲染的,即在第一次被打开之前,传入的默认 slot 不会被渲染到 DOM 上,so在 open 事件回调中进行 | |||
openModel() { | |||
this.$nextTick(() => { | |||
let huashuModel = document.getElementById("huashuModel"); | |||
huashuModel.innerHTML = this.form.originalExpression; | |||
}); | |||
}, | |||
//格式化粘贴文本方法 | |||
onPaste(event) { | |||
var e = event || window.event; | |||
// 阻止默认粘贴 | |||
e.preventDefault(); | |||
// 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
// clipboardData的getData(fomat) 从剪贴板获取指定格式的数据 | |||
var text = | |||
(e.originalEvent || e).clipboardData.getData("text/plain") || | |||
prompt("在这里输入文本"); | |||
//清除回车 | |||
text = text.replace(/\[\d+\]|\n|\r/gi, ""); | |||
// 插入 | |||
document.execCommand("insertText", false, text); | |||
}, | |||
myeditorenter(e) { | |||
e.preventDefault(); | |||
}, | |||
// 插入节点 | |||
insertHtmlAtCaret(html) { | |||
document.getElementById("huashuModel").focus(); | |||
var sel, range; | |||
if (window.getSelection) { | |||
// IE9 and non-IE | |||
sel = window.getSelection(); | |||
if (sel.getRangeAt && sel.rangeCount) { | |||
range = sel.getRangeAt(0); | |||
range.deleteContents(); | |||
// Range.createContextualFragment() would be useful here but is | |||
// non-standard and not supported in all browsers (IE9, for one) | |||
var el = document.createElement("div"); | |||
el.innerHTML = html; | |||
var frag = document.createDocumentFragment(), | |||
node, | |||
lastNode; | |||
while ((node = el.firstChild)) { | |||
lastNode = frag.appendChild(node); | |||
} | |||
range.insertNode(frag); | |||
// Preserve the selection | |||
if (lastNode) { | |||
range = range.cloneRange(); | |||
range.setStartAfter(lastNode); | |||
range.collapse(true); | |||
sel.removeAllRanges(); | |||
sel.addRange(range); | |||
} | |||
} | |||
} else if (document.selection && document.selection.type != "Control") { | |||
// IE < 9 | |||
document.selection.createRange().pasteHTML(html); | |||
} | |||
}, | |||
// 拿问题获取所在的标签数据 | |||
findKeywordsById(level1Id) { | |||
this.wajueList = []; | |||
axios({ | |||
url: `/autoSR/zk/keywords/findKeywordsById`, | |||
method: 'get', | |||
params: { | |||
houseId: this.currentHouseId, | |||
keywordsId: level1Id, | |||
level: 1 | |||
} | |||
}).then((res) => { | |||
if (res.code == 0) { | |||
console.log(res); | |||
this.wajueList = res.data; | |||
if (this.wajueList && this.wajueList.length) { | |||
this.wajueList.forEach((item) => { | |||
item.disabled = false; | |||
}); | |||
} | |||
} | |||
}); | |||
}, | |||
// 插入节点 | |||
insertTag(item, index) { | |||
if (window._range) { | |||
this.insertContent( | |||
"<span contentEditable='false' style='color:red'>" + | |||
item.value + | |||
"</span><text> </text>" | |||
); | |||
} else { | |||
this.insertHtmlAtCaret( | |||
"<span contentEditable='false' style='color:red'>" + | |||
item.value + | |||
"</span><text> </text>" | |||
); | |||
} | |||
}, | |||
searchFun() { | |||
this.tableData = []; | |||
this.pageNum = 1; | |||
this.gettableList(); | |||
}, | |||
//时间选择 | |||
confirmtime() { | |||
this.searchForm.startTime = this.searchForm.customtime[0]; | |||
this.searchForm.endTime = this.searchForm.customtime[1]; | |||
}, | |||
Emptycondition() { | |||
this.searchForm.updateUserName = ""; | |||
this.searchForm.houseName = ""; | |||
this.searchForm.name = ""; | |||
this.searchForm.startTime = ""; | |||
this.searchForm.endTime = ""; | |||
this.searchForm.customtime = []; | |||
this.gettableList(); | |||
}, | |||
changeType() { | |||
this.searchFun(); | |||
}, | |||
gettableList() { | |||
axios({ | |||
url: `/autoSR/zk/todo/list`, | |||
method: "get", | |||
params: { | |||
current: this.pageNum, | |||
size: this.pageSize, | |||
houseName: this.searchForm.houseName, | |||
updateUserName: this.searchForm.updateUserName, | |||
name: this.searchForm.name, | |||
status: this.type, //status 状态 0已处理 1未处理 | |||
startTime: this.searchForm.startTime, | |||
endTime: this.searchForm.endTime, | |||
}, | |||
}).then((res) => { | |||
// console.log(res) | |||
if(res.code==0){ | |||
this.tableData = res.data.records || []; | |||
this.total = res.data.total; | |||
} else { | |||
this.tableData = []; | |||
} | |||
}); | |||
}, | |||
handleSizeChange(val) { | |||
console.log("每页条" + val); | |||
this.pageSize = val; | |||
this.gettableList(); | |||
}, | |||
handleCurrentChange(val) { | |||
console.log("当前页" + val); | |||
this.pageNum = val; | |||
this.gettableList(); | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped="scoped" lang="scss"> | |||
// /deep/ .el-table__header-wrapper{ | |||
// thead{ | |||
// tr{ | |||
// th{ | |||
// background: #F5F7FA; | |||
// color: #333333; | |||
// } | |||
// } | |||
// } | |||
// } | |||
.box-center { | |||
width: 100%; | |||
padding: 5px 15px 40px; | |||
min-width: 1000px; | |||
} | |||
.app-top { | |||
width: 100%; | |||
background: #ffffff; | |||
box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.04); | |||
border-radius: 4px; | |||
padding-top: 15px; | |||
padding-bottom: 15px; | |||
.app-titel { | |||
width: 100%; | |||
display: flex; | |||
align-items: center; | |||
.label { | |||
font-size: 14px; | |||
font-weight: 400; | |||
color: #32363d; | |||
line-height: 14px; | |||
margin-left: 15px; | |||
// min-width: 100px; | |||
text-align: right; | |||
} | |||
} | |||
.control-tab { | |||
margin-left: 15px; | |||
} | |||
} | |||
.button1 { | |||
padding-left: 16px; | |||
padding-right: 16px; | |||
height: 32px; | |||
line-height: 32px; | |||
background: #2671e2; | |||
border-radius: 2px; | |||
color: #ffffff; | |||
font-size: 16px; | |||
border: none; | |||
cursor: pointer; | |||
} | |||
.el-pagination { | |||
display: flex; | |||
justify-content: flex-end; | |||
margin-top: 20px; | |||
} | |||
.editDiv { | |||
width: 100%; | |||
min-height: 60px; | |||
max-height: 120px; | |||
overflow: auto; | |||
margin-bottom: 10px; | |||
padding: 15px; | |||
outline: none; | |||
border: 1px solid #409eff; | |||
border-radius: 10px; | |||
box-sizing: border-box; | |||
} | |||
.itemlist { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
margin: 20px 0; | |||
} | |||
.item-input { | |||
width: 100%; | |||
padding: 4px 10px; | |||
outline: none; | |||
border: 1px solid #409eff; | |||
border-radius: 4px; | |||
overflow: auto; | |||
line-height: 24px; | |||
min-height: 24px; | |||
max-height: 100px; | |||
margin: 0 10px; | |||
} | |||
.el-dialog { | |||
width: 800px; | |||
} | |||
.el-dialog__body { | |||
max-height: 400px; | |||
overflow: auto; | |||
} | |||
</style> |
@@ -34,14 +34,14 @@ export default { | |||
label: "模板名称", | |||
prop: "templateName", | |||
}, | |||
{ | |||
label: "默认话术", | |||
prop: "defaultTemplate", | |||
formatter: (data) => { | |||
if(data.defaultTemplate == 0) return '是' | |||
if(data.defaultTemplate == 1) return '否' | |||
} | |||
}, | |||
// { | |||
// label: "默认话术", | |||
// prop: "defaultTemplate", | |||
// formatter: (data) => { | |||
// if(data.defaultTemplate == 0) return '是' | |||
// if(data.defaultTemplate == 1) return '否' | |||
// } | |||
// }, | |||
{ | |||
label: "大类个数", | |||
prop: "count", | |||
@@ -64,19 +64,16 @@ | |||
> | |||
<template slot-scope="{ row }" slot="menu"> | |||
<el-button v-if="tem_tab_edit" type="text" @click="bianji(row)" | |||
>编辑</el-button | |||
> | |||
<el-button v-if="tem_tab_del" type="text" @click="del(row)" | |||
>删除</el-button | |||
> | |||
>编辑</el-button> | |||
<el-button v-if="tem_tab_del" type="text" @click="del(row)">删除</el-button> | |||
<el-button v-if="permissions.jinjihuashumoxingpipei" type="text" @click="editFun(row)">模型匹配</el-button> | |||
</template> | |||
</avue-crud> | |||
</div> | |||
<el-dialog | |||
:title="editFlag ? '编辑' : '新增'" | |||
:center="true" | |||
width="400px" | |||
width="600px" | |||
:visible.sync="dialogVisible" | |||
@close="$refs.ruleForm.resetFields()" | |||
> | |||
@@ -85,7 +82,7 @@ | |||
label-position="labelPosition" | |||
:rules="ruleser" | |||
ref="ruleForm" | |||
label-width="66px" | |||
label-width="80px" | |||
style="width: 100%; margin: 0 auto" | |||
> | |||
<el-form-item label="敏感词" prop="words"> | |||
@@ -96,6 +93,17 @@ | |||
clearable | |||
></el-input> | |||
</el-form-item> | |||
<el-form-item label="场景描述" prop="sceneDesc"> | |||
<el-input | |||
type="textarea" | |||
v-model="ruleForm.sceneDesc" | |||
placeholder="敏感词" | |||
maxlength="100" | |||
show-word-limit | |||
clearable | |||
></el-input> | |||
<div>增加场景描述有利于标签命中,场景越丰富触达越精准;例如:送家具 ,场景:现在买房我们送家具;</div> | |||
</el-form-item> | |||
</el-form> | |||
<div | |||
slot="footer" | |||
@@ -104,24 +112,96 @@ | |||
border-top: 1px solid #eee; | |||
padding-top: 20px; | |||
display: flex; | |||
justify-content: end; | |||
" | |||
> | |||
justify-content: end;"> | |||
<el-button @click="dialogVisible = false">取 消</el-button> | |||
<el-button type="primary" :loading="loadingFlag" @click="editor()" | |||
>保存</el-button | |||
> | |||
<el-button type="primary" :loading="loadingFlag" @click="editor()">保存</el-button > | |||
</div> | |||
</el-dialog> | |||
<el-dialog | |||
title="编辑模型" | |||
@open="openModel" | |||
:close-on-click-modal="false" | |||
:visible.sync="modelVisible" | |||
> | |||
<matching-rules :key="timer" :innerVisible="innerVisible"></matching-rules> | |||
<el-form ref="form" size="mini" :inline="true" :model="form" label-position="right"> | |||
<el-form-item label="敏感词:"> | |||
<div style="max-width:400px;min-width: 200px;font-weight: bold">{{form.keywordsName||''}}</div> | |||
</el-form-item> | |||
<el-form-item label="场景描述:"> | |||
<div v-if="form.sceneDesc" style="width:500px;border: 1px dashed #ccc;padding:5px 10px;line-height: 25px"> {{form.sceneDesc}}</div> | |||
<div v-else>暂无描述</div> | |||
</el-form-item> | |||
<el-form-item label="after,near,answer 匹配距离:"> | |||
<el-input-number v-model="form.distance" controls-position="right" :min="0" :max="500"></el-input-number> | |||
<span style="color:red;margin-left:10px">*请输入0~500内的整数</span> | |||
<el-button type="text" style="margin-left:30px" @click="innerVisible=true;timer=new Date().getTime()">规则说明</el-button> | |||
</el-form-item> | |||
<div contentEditable="true" | |||
@click="myeditorenter($event)" | |||
@keypress.enter="myeditorenter($event)" | |||
@blur="saveRange" | |||
@paste="onPaste" | |||
class="editDiv" | |||
id="huashuModel"> | |||
</div> | |||
<el-form-item label="插入节点:"> | |||
<el-button size="mini" type="primary" style="margin-left:8px;" v-for="(item,index) in taglist" :key="index" @click="insertTag(item,index)">{{item.label}}</el-button> | |||
</el-form-item> | |||
</el-form> | |||
<span slot="footer" class="dialog-footer"> | |||
<el-button @click="modelVisible = false">取 消</el-button> | |||
<el-button type="primary" @click="saveFun">保 存</el-button> | |||
</span> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapGetters } from "vuex"; | |||
import { exportMethodPost } from "@/util/util"; | |||
import matchingRules from "@/components/matchingRules/matchingRules.vue"; | |||
export default { | |||
components: { matchingRules }, | |||
data() { | |||
return { | |||
dynamiclist: [], | |||
taglist:[ | |||
{ | |||
label: 'or (或)', | |||
value: 'or' | |||
}, | |||
{ | |||
label: 'near (临近)', | |||
value: 'near' | |||
}, | |||
{ | |||
label: 'after (后面)', | |||
value: 'after' | |||
}, | |||
{ | |||
label: 'and not (非)', | |||
value: 'andnot' | |||
}, | |||
// { | |||
// label: '~ (至)', | |||
// value: '~' | |||
// }, | |||
], | |||
form: { | |||
keywordsName: '', | |||
id: '', | |||
keywordsId: '', | |||
distance: 10, | |||
sceneDesc:'', | |||
originalExpression: '' | |||
}, | |||
modelVisible:false, | |||
innerVisible:false, | |||
innerVisible1:false, | |||
dialogVisible: false, | |||
tableIdName: "TemplateTaboo", // 当前页面需要的变量 | |||
tableOption: this.$tableOption.TemplateTaboo, // 当前table配置项 | |||
tableLoading: false, // 是否显示加载中 | |||
@@ -137,11 +217,11 @@ export default { | |||
input: "", | |||
tableData: [], | |||
multipleSelection: [], | |||
dialogVisible: false, | |||
loadingFlag: false, | |||
orgType: localStorage.getItem("orgType"), | |||
ruleForm: { | |||
words: "", | |||
sceneDesc: '', | |||
id: "", | |||
}, | |||
houseId: "", | |||
@@ -169,6 +249,7 @@ export default { | |||
}, | |||
created() { | |||
this.houseId=localStorage.getItem("houseId"); | |||
// 获取显隐的列表 | |||
this.setTableOption(); | |||
this.tem_tab_add = this.permissions["tem_tab_add"]; | |||
@@ -180,6 +261,344 @@ export default { | |||
this.zkhousePage(); | |||
}, | |||
methods: { | |||
// 插入节点 | |||
insertTag(item,index){ | |||
if(window._range){ | |||
this.insertContent("<span contentEditable='false' style='color:red'>"+item.value+"</span><text> </text>"); | |||
}else{ | |||
this.insertHtmlAtCaret("<span contentEditable='false' style='color:red'>"+item.value+"</span><text> </text>"); | |||
} | |||
}, | |||
// 处理标签,删除不需要的标签格式 | |||
delMark(str) { | |||
const hasStr = (str) => { | |||
let index = str.indexOf('<') | |||
let index1 = str.indexOf('>') | |||
if(index>0&&index1>0){ | |||
let replaceStr= str.substring(index, index1+1) | |||
str= str.replace(replaceStr,'') | |||
hasStr(str) | |||
} | |||
} | |||
hasStr(str) | |||
}, | |||
// 确认插入选择的话术 | |||
clickOK(){ | |||
this.innerVisible1 = false | |||
if(!this.huashu) {this.$message.error('请选择话术'); return ;} | |||
this.insertContent("<text>"+this.huashu+"</text><span contentEditable='false' style='color:red'>answer</span><text> </text>"); | |||
}, | |||
//点击编辑按钮 | |||
editFun(row){ | |||
this.form.keywordsId = row.id | |||
this.form.keywordsName = row.words||'' | |||
this.form.id = '' | |||
// 获取模型数据回显 | |||
axios({ | |||
url: `/autoSR/zk/keymodel/findById`, | |||
method: 'get', | |||
params: { | |||
houseId: this.houseId, | |||
keyType: 3, | |||
keywordsId: row.id | |||
} | |||
}).then(res => { | |||
this.modelVisible = true | |||
if (res.code == 0) { | |||
let obj = res.data | |||
if(obj!=null){ | |||
this.form.distance = obj.distance||10 | |||
this.form.originalExpression = obj.originalExpression | |||
this.form.id = obj.id | |||
this.form.sceneDesc = obj.desc||'' | |||
this.form.keywordsName = obj.level1Name | |||
}else{ | |||
this.form.distance=10 | |||
this.form.id = '' | |||
this.form.originalExpression='' | |||
} | |||
}else{ | |||
this.form.distance = 10 | |||
this.form.originalExpression = '' | |||
this.form.id = '' | |||
} | |||
this.$nextTick(()=>{ | |||
let huashuModel = document.getElementById('huashuModel') | |||
huashuModel.innerHTML = this.form.originalExpression | |||
}) | |||
}).catch((e)=>{ | |||
this.modelVisible = true | |||
}) | |||
}, | |||
// 处理模型 关键词加#号 | |||
replaceFun(str){ | |||
let temp = str | |||
temp = temp.replace(/<text>\ \;<\/text>/g,''); | |||
temp = temp.replace(/\ \;/g,''); | |||
temp = temp.replace(/<text>/g,''); | |||
temp = temp.replace(/<\/text>/g,''); | |||
temp = temp.replace(/<span contenteditable="false" style="color:red">/g,' #');// 后台返回是这样的,变了,需要也处理一下 | |||
temp = temp.replace(/<span style="color:red" contenteditable="false">/g,' #'); | |||
temp = temp.replace(/<\/br>/g,'') | |||
temp = temp.replace(/<br>/g,'') | |||
temp = temp.replace(/<\/span>/g,'#') | |||
// console.log('处理前temp',temp); | |||
this.delMark(temp); | |||
// console.log(temp); | |||
return temp | |||
}, | |||
// 模型保存 | |||
saveFun(){ | |||
let text = document.getElementById('huashuModel'); | |||
// console.log(text.innerHTML); | |||
// console.log(text.innerText); | |||
let temp = text.innerHTML | |||
if(this.form.distance=='') {this.$message.error('请输入距离'); return;} | |||
if(text.innerText=='') {this.$message.error('请输入标签模型'); return;} | |||
axios({ | |||
url: `/autoSR/zk/keymodel/updateKeywordsModel`, | |||
method: 'post', | |||
data: { | |||
id: this.form.id||"", | |||
houseId: this.houseId, | |||
level: 1, | |||
keywordsId: this.form.keywordsId, | |||
keywordsName: this.form.keywordsName, | |||
answerList: [], | |||
keyType: 3, | |||
formatExpression: this.replaceFun(temp),// 问题表达式 | |||
original: temp,// html数据 | |||
showFormatExpression: text.innerText, | |||
distance: this.form.distance, // * 距离 | |||
desc: this.form.sceneDesc//场景描述 | |||
} | |||
}).then(res => { | |||
this.dialogVmodelVisibleisible = false | |||
if(res.code==0){ | |||
this.$message.success(res.data) | |||
this.getorgCode() | |||
}else{ | |||
this.$message.error(res.msg) | |||
} | |||
}).catch((e)=>{ | |||
this.modelVisible = false | |||
}) | |||
}, | |||
// 失去焦点时保存光标位置,记录光标位置 | |||
saveRange: () => { | |||
let selection = window.getSelection ? window.getSelection() : document.selection; | |||
if (!selection.rangeCount) return; | |||
let range = selection.createRange ? selection.createRange() : selection.getRangeAt(0); | |||
window._range = range; | |||
}, | |||
// 回显模型数据,Dialog 的内容是懒渲染的,即在第一次被打开之前,传入的默认 slot 不会被渲染到 DOM 上,so在 open 事件回调中进行 | |||
openModel(){ | |||
this.$nextTick(()=>{ | |||
let huashuModel = document.getElementById('huashuModel') | |||
huashuModel.innerHTML = this.form.originalExpression | |||
}) | |||
}, | |||
//格式化粘贴文本方法 | |||
onPaste(event) { | |||
// var e = event || window.event | |||
// // 阻止默认粘贴 | |||
// e.preventDefault(); | |||
// // 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
// // clipboardData的getData(fomat) 从剪贴板获取指定格式的数据 | |||
// var text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('在这里输入文本'); | |||
// //清除回车 | |||
// text = text.replace(/\[\d+\]|\n|\r/ig,"") | |||
// // 插入 | |||
// document.execCommand("insertText", false, text); | |||
let e = event || window.event | |||
let types = event.clipboardData.types | |||
// 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
let flag = false | |||
if (types && types.length > 0) { | |||
types.forEach(ele => { | |||
if (ele == 'Files') { | |||
flag = true | |||
} | |||
}) | |||
} | |||
if (flag) { | |||
event.preventDefault() | |||
} | |||
}, | |||
myeditorenter(e) { | |||
e.preventDefault(); | |||
}, | |||
// 插入节点 | |||
insertHtmlAtCaret(html) { | |||
document.getElementById('huashuModel').focus(); | |||
var sel, range; | |||
if (window.getSelection) { | |||
// IE9 and non-IE | |||
sel = window.getSelection(); | |||
if (sel.getRangeAt && sel.rangeCount) { | |||
range = sel.getRangeAt(0); | |||
range.deleteContents(); | |||
// Range.createContextualFragment() would be useful here but is | |||
// non-standard and not supported in all browsers (IE9, for one) | |||
var el = document.createElement("div"); | |||
el.innerHTML = html; | |||
var frag = document.createDocumentFragment(), | |||
node, lastNode; | |||
while ((node = el.firstChild)) { | |||
lastNode = frag.appendChild(node); | |||
} | |||
range.insertNode(frag); | |||
// Preserve the selection | |||
if (lastNode) { | |||
range = range.cloneRange(); | |||
range.setStartAfter(lastNode); | |||
range.collapse(true); | |||
sel.removeAllRanges(); | |||
sel.addRange(range); | |||
} | |||
} | |||
} else if (document.selection && document.selection.type != "Control") { | |||
// IE < 9 | |||
document.selection.createRange().pasteHTML(html); | |||
} | |||
}, | |||
// 校验是否已经选择过此标签 | |||
checkrepeat(){ | |||
this.wajueList.forEach(item=>{ | |||
item.disabled = false | |||
}) | |||
this.wajueList.forEach(item=>{ | |||
this.dynamiclist.forEach(obj=>{ | |||
if(item.id==obj.markid){ | |||
item.disabled = true | |||
} | |||
}) | |||
}) | |||
}, | |||
addItemFun(){ | |||
this.dynamiclist.push({ | |||
editValue: '',//匹配模型正则表达式 | |||
markid:'', | |||
level: '', | |||
name:'' | |||
}) | |||
}, | |||
delItemFun(index){ | |||
this.wajueList.forEach(item=>{ | |||
if(item.id==this.dynamiclist[index].markid){ | |||
item.disabled = false | |||
} | |||
}) | |||
this.dynamiclist.splice(index,1) | |||
document.getElementById('huashuModel').focus(); // 防止插入到外面,造成不可删除的操作 | |||
}, | |||
// 基于保存的光标插入内容 --用于失去焦点后再继续插入内容 | |||
insertContent(str) { | |||
let selection, range = window._range;// 当前光标位置对象 | |||
if (!window.getSelection) { | |||
range.pasteHTML(str); | |||
range.collapse(false); | |||
range.select(); | |||
} else { | |||
selection = window.getSelection ? window.getSelection() : document.selection; | |||
range.collapse(false); | |||
let hasR = range.createContextualFragment(str); | |||
let hasR_lastChild = hasR.lastChild; | |||
while (hasR_lastChild && hasR_lastChild.nodeName.toLowerCase() == "br" && hasR_lastChild.previousSibling && hasR_lastChild.previousSibling.nodeName.toLowerCase() == "br") { | |||
let e = hasR_lastChild; | |||
hasR_lastChild = hasR_lastChild.previousSibling; | |||
hasR.removeChild(e); | |||
} | |||
range.insertNode(hasR); | |||
if (hasR_lastChild) { | |||
range.setEndAfter(hasR_lastChild); | |||
range.setStartAfter(hasR_lastChild); | |||
} | |||
selection.removeAllRanges(); | |||
selection.addRange(range); | |||
} | |||
}, | |||
// 失去焦点时保存光标位置,记录光标位置 | |||
saveRange: () => { | |||
let selection = window.getSelection ? window.getSelection() : document.selection; | |||
if (!selection.rangeCount) return; | |||
let range = selection.createRange ? selection.createRange() : selection.getRangeAt(0); | |||
window._range = range; | |||
}, | |||
// 回显模型数据,Dialog 的内容是懒渲染的,即在第一次被打开之前,传入的默认 slot 不会被渲染到 DOM 上,so在 open 事件回调中进行 | |||
openModel(){ | |||
this.$nextTick(()=>{ | |||
let huashuModel = document.getElementById('huashuModel') | |||
huashuModel.innerHTML = this.form.originalExpression | |||
}) | |||
}, | |||
//格式化粘贴文本方法 | |||
onPaste(event) { | |||
// var e = event || window.event | |||
// // 阻止默认粘贴 | |||
// e.preventDefault(); | |||
// // 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
// // clipboardData的getData(fomat) 从剪贴板获取指定格式的数据 | |||
// var text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('在这里输入文本'); | |||
// //清除回车 | |||
// text = text.replace(/\[\d+\]|\n|\r/ig,"") | |||
// // 插入 | |||
// document.execCommand("insertText", false, text); | |||
let e = event || window.event | |||
let types = event.clipboardData.types | |||
// 粘贴事件有一个clipboardData的属性,提供了对剪贴板的访问 | |||
let flag = false | |||
if (types && types.length > 0) { | |||
types.forEach(ele => { | |||
if (ele == 'Files') { | |||
flag = true | |||
} | |||
}) | |||
} | |||
if (flag) { | |||
event.preventDefault() | |||
} | |||
}, | |||
myeditorenter(e) { | |||
e.preventDefault(); | |||
}, | |||
// 插入节点 | |||
insertHtmlAtCaret(html) { | |||
document.getElementById('huashuModel').focus(); | |||
var sel, range; | |||
if (window.getSelection) { | |||
// IE9 and non-IE | |||
sel = window.getSelection(); | |||
if (sel.getRangeAt && sel.rangeCount) { | |||
range = sel.getRangeAt(0); | |||
range.deleteContents(); | |||
// Range.createContextualFragment() would be useful here but is | |||
// non-standard and not supported in all browsers (IE9, for one) | |||
var el = document.createElement("div"); | |||
el.innerHTML = html; | |||
var frag = document.createDocumentFragment(), | |||
node, lastNode; | |||
while ((node = el.firstChild)) { | |||
lastNode = frag.appendChild(node); | |||
} | |||
range.insertNode(frag); | |||
// Preserve the selection | |||
if (lastNode) { | |||
range = range.cloneRange(); | |||
range.setStartAfter(lastNode); | |||
range.collapse(true); | |||
sel.removeAllRanges(); | |||
sel.addRange(range); | |||
} | |||
} | |||
} else if (document.selection && document.selection.type != "Control") { | |||
// IE < 9 | |||
document.selection.createRange().pasteHTML(html); | |||
} | |||
}, | |||
// 获取当前页面的显隐 | |||
setTableOption() { | |||
this.$db.getDataByKey(this.tableIdName).then((res) => { | |||
@@ -193,7 +612,6 @@ export default { | |||
houseId: this.houseId, | |||
words: this.words, | |||
}; | |||
// exportMethodPost() | |||
exportMethodPost("autoSR/sensitivewords/export", "禁忌话术", obj); | |||
}, | |||
houseChange() { | |||
@@ -213,7 +631,6 @@ export default { | |||
} else { | |||
this.houseId = res.data[0].id; | |||
} | |||
// this.houseId = res.data[0].id; | |||
this.taboofindbypagelist(); | |||
}); | |||
}, | |||
@@ -251,7 +668,7 @@ export default { | |||
type: "warning", | |||
}) | |||
.then(() => { | |||
this.$api.http.taboodelete({ id: item.id }).then((res) => { | |||
this.$api.http.taboodelete({ id: item.id,houseId:this.houseId }).then((res) => { | |||
if (res.code == 0) { | |||
this.$message({ | |||
type: "success", | |||
@@ -261,7 +678,7 @@ export default { | |||
this.words = ""; | |||
this.taboofindbypagelist(); | |||
} else { | |||
this.$message.error(res.message); | |||
this.$message.error(res.msg); | |||
} | |||
}); | |||
}) | |||
@@ -277,6 +694,7 @@ export default { | |||
this.ruleForm.id = row.id; | |||
this.dialogVisible = true; | |||
this.ruleForm.words = row.words; | |||
this.ruleForm.sceneDesc = row.desc; | |||
this.editFlag = true; | |||
}, | |||
@@ -288,16 +706,17 @@ export default { | |||
editor() { | |||
this.$refs.ruleForm.validate((valid) => { | |||
if (valid) { | |||
if (this.hasOwn.indexOf(this.ruleForm.words) != -1) { | |||
this.$message.error("该敏感词已存在"); | |||
return; | |||
} | |||
// if (this.hasOwn.indexOf(this.ruleForm.words) != -1) { | |||
// this.$message.error("该敏感词已存在"); | |||
// return; | |||
// } | |||
this.loadingFlag = true; | |||
if (this.editFlag == false) { | |||
this.$api.http | |||
.tabooadd({ | |||
houseId: this.houseId, | |||
words: this.ruleForm.words, | |||
desc: this.ruleForm.sceneDesc// 场景描述 | |||
}) | |||
.then((res) => { | |||
if (res.code == 0) { | |||
@@ -305,26 +724,28 @@ export default { | |||
this.$refs.ruleForm.resetFields(); | |||
this.page.currentPage = 1; | |||
this.words = ""; | |||
this.ruleForm.sceneDesc = ''; | |||
this.taboofindbypagelist(); | |||
this.$message.success(res.data); | |||
} else { | |||
this.$message.error(res.message); | |||
this.$message.error(res.msg); | |||
} | |||
setTimeout(() => { | |||
this.loadingFlag = false; | |||
console.log("防重"); | |||
}, 1); | |||
}) | |||
.catch((e) => { | |||
setTimeout(() => { | |||
this.loadingFlag = false; | |||
console.log("防重"); | |||
}, 1); | |||
}); | |||
} else { | |||
this.$api.http | |||
.tabooupdate({ | |||
id: this.ruleForm.id, | |||
desc: this.ruleForm.sceneDesc, | |||
words: this.ruleForm.words, | |||
houseId: this.houseId, | |||
}) | |||
.then((res) => { | |||
if (res.code == 0) { | |||
@@ -332,19 +753,19 @@ export default { | |||
this.$refs.ruleForm.resetFields(); | |||
this.page.currentPage = 1; | |||
this.words = ""; | |||
this.ruleForm.sceneDesc = ''; | |||
this.taboofindbypagelist(); | |||
this.$message.success(res.data); | |||
} else { | |||
this.$message.error(res.message); | |||
this.$message.error(res.msg); | |||
} | |||
setTimeout(() => { | |||
this.loadingFlag = false; | |||
console.log("防重"); | |||
}, 1); | |||
}) | |||
.catch((e) => { | |||
setTimeout(() => { | |||
this.loadingFlag = false; | |||
console.log("防重"); | |||
}, 1); | |||
}); | |||
} | |||
@@ -368,6 +789,17 @@ export default { | |||
</script> | |||
<style scoped="scoped" lang="scss" > | |||
.editDiv{ | |||
width:100%; | |||
min-height:60px; | |||
max-height:120px; | |||
overflow:auto; | |||
margin-bottom:10px; | |||
padding: 15px; | |||
outline: none; | |||
border:1px solid #409EFF; | |||
border-radius: 10px; | |||
} | |||
.box-center { | |||
width: 100%; | |||
padding: 5px 15px 20px; | |||
@@ -286,8 +286,6 @@ export default { | |||
if (valid) { | |||
// 编辑 | |||
if (this.editFlag) { | |||
console.log("编辑"); | |||
if (this.mistakenList.indexOf(this.ruleForm.correctWord) != -1) { | |||
this.$message.error("正确词不能与错误词相同"); | |||
return; | |||
@@ -297,16 +295,13 @@ export default { | |||
this.$message.error("错误词不能与正确词相同"); | |||
return; | |||
} | |||
console.log(this.searchForm.houseId) | |||
this.$api.api.correctUpdate({ | |||
...this.ruleForm, | |||
houseId: this.searchForm.houseId | |||
}).then((res) => { | |||
console.log(res); | |||
if (res.code == 0) { | |||
setTimeout(() => { | |||
this.loadingFlag = false; | |||
console.log("防重"); | |||
}, 1); | |||
this.dialogVisible = false; | |||
this.$message.success("编辑成功"); | |||
@@ -325,11 +320,10 @@ export default { | |||
...this.ruleForm, | |||
}) | |||
.then((res) => { | |||
console.log(res); | |||
// console.log(res); | |||
if (res.code == 0) { | |||
setTimeout(() => { | |||
this.loadingFlag = false; | |||
console.log("防重"); | |||
}, 1); | |||
this.dialogVisible = false; | |||
this.$message.success("新增常错词成功"); | |||
@@ -880,8 +880,8 @@ export default { | |||
time: "22:00", // 日报推送时间 | |||
closeTime: "120", // 接待时长(自动结束) | |||
offLine: ["08:00", "20:00"], // 离线推送时间段 | |||
caseShow: '0', // 优秀案例 | |||
tagMatching: '0', // 客户标签匹配 | |||
caseShow: 0, // 优秀案例 | |||
tagMatching: 0, // 客户标签匹配 | |||
transliterationMethod: '',//转写方式 | |||
language:'',//语言 | |||
}, | |||
@@ -2,14 +2,8 @@ | |||
* 配置参考: | |||
* https://cli.vuejs.org/zh/config/ | |||
*/ | |||
const url = 'http://192.168.31.160:9999' //长龙 | |||
// const url = 'http://192.168.31.85:9999' // 胜浩 | |||
// const url = 'http://127.0.0.1:9999' // 本地 | |||
// const url = 'http://39.97.244.65:9999' // 测试服务器 | |||
// const url = 'http://62.234.122.43:9999' //正式服务器1 | |||
// const url = 'https://www.aihxz.com' // 正式域名 | |||
const url = process.env.VUE_APP_BASE_API // 配置.env文件通过运行命令启动不同调试环境 | |||
const CompressionWebpackPlugin = require('compression-webpack-plugin') | |||
const productionGzipExtensions = ['js', 'css'] | |||
module.exports = { | |||