Browse Source

合并主分支

newStyle
douzhuo 1 year ago
parent
commit
db1ac7b773
30 changed files with 6637 additions and 3577 deletions
  1. +1
    -0
      .env.cldevelopment
  2. +1
    -0
      .env.development
  3. +1
    -0
      .env.localdevelopment
  4. +1
    -0
      .env.production
  5. +1
    -0
      .env.shdevelopment
  6. +4
    -0
      package.json
  7. +1
    -0
      src/App.vue
  8. +69
    -0
      src/api/modules/api.js
  9. +124
    -0
      src/components/matchingRules/matchingRules.vue
  10. +6
    -6
      src/page/check/chose.vue
  11. +134
    -31
      src/page/wel.vue
  12. +1
    -0
      src/router/axios.js
  13. +2
    -2
      src/views/Customer/index.vue
  14. +432
    -23
      src/views/Customer/label.vue
  15. +0
    -3078
      py.vue
  16. +572
    -143
      src/views/Receive/index.vue
  17. +244
    -95
      src/views/ReceivingRecords/index.vue
  18. +48
    -6
      src/views/ReceivingRecords/table.js
  19. +8
    -7
      src/views/Statistics/MentoringAbility.vue
  20. +2
    -125
      src/views/Statistics/ReceptionOverview.vue
  21. +8
    -8
      src/views/Template/Pinspeakwords.vue
  22. +773
    -0
      src/views/Template/labelModel.vue
  23. +836
    -0
      src/views/Template/modelTodo.vue
  24. +1513
    -0
      src/views/Template/requiremining.vue
  25. +1382
    -0
      src/views/Template/requireminingAnalysis.vue
  26. +8
    -8
      src/views/Template/table.js
  27. +461
    -29
      src/views/Template/taboo.vue
  28. +1
    -7
      src/views/Template/wrongword.vue
  29. +2
    -2
      src/views/building/index.vue
  30. +1
    -7
      vue.config.js

+ 1
- 0
.env.cldevelopment View File

@@ -0,0 +1 @@
VUE_APP_BASE_API = 'http://192.168.31.160:9999'

+ 1
- 0
.env.development View File

@@ -0,0 +1 @@
VUE_APP_BASE_API = 'http://39.97.244.65:9999'

+ 1
- 0
.env.localdevelopment View File

@@ -0,0 +1 @@
VUE_APP_BASE_API = 'http://127.0.0.1:9999'

+ 1
- 0
.env.production View File

@@ -0,0 +1 @@
VUE_APP_BASE_API = 'https://www.aihxz.com'

+ 1
- 0
.env.shdevelopment View File

@@ -0,0 +1 @@
VUE_APP_BASE_API = 'http://192.168.31.85:9999'

+ 4
- 0
package.json View File

@@ -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"


+ 1
- 0
src/App.vue View File

@@ -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: {}
}


+ 69
- 0
src/api/modules/api.js View File

@@ -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
})
}





+ 124
- 0
src/components/matchingRules/matchingRules.vue View File

@@ -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>

+ 6
- 6
src/page/check/chose.vue View File

@@ -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">


+ 134
- 31
src/page/wel.vue View File

@@ -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;


+ 1
- 0
src/router/axios.js View File

@@ -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){


+ 2
- 2
src/views/Customer/index.vue View File

@@ -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();
});
},
// 置业顾问列表


+ 432
- 23
src/views/Customer/label.vue View File

@@ -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>&nbsp;</text>");
}else{
this.insertHtmlAtCaret("<span contentEditable='false' style='color:red'>"+item.value+"</span><text>&nbsp;</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>\&nbsp\;<\/text>/g,'');
temp = temp.replace(/\&nbsp\;/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>

py.vue
File diff suppressed because it is too large
View File


+ 572
- 143
src/views/Receive/index.vue View File

@@ -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;


+ 244
- 95
src/views/ReceivingRecords/index.vue View File

@@ -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;
}



+ 48
- 6
src/views/ReceivingRecords/table.js View File

@@ -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}%`
}


+ 8
- 7
src/views/Statistics/MentoringAbility.vue View File

@@ -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%;


+ 2
- 125
src/views/Statistics/ReceptionOverview.vue View File

@@ -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()}-${


+ 8
- 8
src/views/Template/Pinspeakwords.vue View File

@@ -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;
}


+ 773
- 0
src/views/Template/labelModel.vue View File

@@ -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>&nbsp;</text>"
);
} else {
this.insertHtmlAtCaret(
"<span contentEditable='false' style='color:red'>" +
item.value +
"</span><text>&nbsp;</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>&nbsp;</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>\&nbsp\;<\/text>/g, "");
temp = temp.replace(/\&nbsp\;/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>

+ 836
- 0
src/views/Template/modelTodo.vue View File

@@ -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>\&nbsp\;<\/text>/g, "");
temp = temp.replace(/\&nbsp\;/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>&nbsp;</text>"
);
} else {
this.insertHtmlAtCaret(
"<span contentEditable='false' style='color:red'>" +
item.value +
"</span><text>&nbsp;</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>

+ 1513
- 0
src/views/Template/requiremining.vue
File diff suppressed because it is too large
View File


+ 1382
- 0
src/views/Template/requireminingAnalysis.vue
File diff suppressed because it is too large
View File


+ 8
- 8
src/views/Template/table.js View File

@@ -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",


+ 461
- 29
src/views/Template/taboo.vue View File

@@ -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>&nbsp;</text>");
}else{
this.insertHtmlAtCaret("<span contentEditable='false' style='color:red'>"+item.value+"</span><text>&nbsp;</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>&nbsp;</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>\&nbsp\;<\/text>/g,'');
temp = temp.replace(/\&nbsp\;/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;


+ 1
- 7
src/views/Template/wrongword.vue View File

@@ -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("新增常错词成功");


+ 2
- 2
src/views/building/index.vue View File

@@ -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:'',//语言
},


+ 1
- 7
vue.config.js View File

@@ -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 = {


Loading…
Cancel
Save