feat: 数字民警开发

ocr_2.1
xiangcongshuai 7 months ago
parent 614cc5fc54
commit f0d82b768c

@ -97,4 +97,30 @@ export function getCaseScore(data) {
method: 'get', method: 'get',
params: data params: data
}) })
}
/** 查询用户对话列表 */
export function conversationList(data) {
return request({
url: `/robot/conversation/list`,
method: 'get',
params: data
})
}
/** 查询对话内容列表 */
export function conversationInfoList(data) {
return request({
url: `/robot/conversation/infoList`,
method: 'get',
params: data
})
}
/** 删除对话 */
export function conversationDelete(data) {
return request({
url: `/robot/conversation/delete`,
method: 'post',
data
})
} }

@ -12,6 +12,8 @@ import request from '@/utils/request'
/** 下载文件 */ /** 下载文件 */
export const commonDownloadFile = `${routes.minio}/downloadFile?fileId=` export const commonDownloadFile = `${routes.minio}/downloadFile?fileId=`
/** 下载证据压缩包 */
export const downloadEvidence = `/caseEvidence/downloadEvidence?evidenceId=`
/** 删除文件 */ /** 删除文件 */
export const commonDeleteFile = `${routes.minio}/delFile?fileId=` export const commonDeleteFile = `${routes.minio}/delFile?fileId=`

@ -0,0 +1,295 @@
<template>
<div class="historical-records">
<div class="top">
<img src="../../assets/police/robot.png" alt="">
<span>伏小羲</span>
</div>
<div class="main-new-item" @click="onBtnClicked">
<img src="@/assets/common/new.png" alt="">
<span>新对话</span>
</div>
<div v-if="caseList.length > 0">
<div class="main-message-item">
<img src="@/assets/common/message.png" alt="">
<span>最近半年</span>
</div>
<div v-if="!delFlag" class="case-list">
<span v-for="(item,index) in caseList" :key="index" :class="[selectId === item.conversationId ? 'actived' :'']" class="case-item" @click.stop="selectCase(item)">
<span>{{ item.caseName }}</span>
<i class="el-icon-delete file-delete" @click.stop="delCase(item)" />
</span>
</div>
<div v-if="delFlag" class="del-case-list">
<el-checkbox-group v-model="checkedCase" class="case-group" @change="handleCheckedChange">
<el-checkbox v-for="item in caseList" :key="item.conversationId" :label="item.conversationId">{{ item.caseName }}</el-checkbox>
</el-checkbox-group>
</div>
<div v-if="!delFlag" class="footer" @click="changeDelFlag">
<i class="el-icon-delete file-delete" />
<span>批量删除</span>
</div>
<div v-if="delFlag" class="del-footer">
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange"></el-checkbox>
<span class="del-item" @click="delAll">
<i class="el-icon-delete file-delete" />
<span>删除</span>
</span>
<span class="logout" @click="changeDelFlag">
<i class="el-icon-switch-button" />
<span>退出</span>
</span>
</div>
</div>
<div v-else class="empty">
<span>最近半年 无对话内容</span>
</div>
</div>
</template>
<script>
import { conversationList, conversationDelete } from '@/api/caseManagement'
export default {
name: 'HistoricalRecords',
data() {
return {
checkAll: false,
selectId: '',
caseList: [
],
isIndeterminate: true,
checkedCase: [],
delFlag: false,
showCaseList: []
}
},
mounted() {
this.getList()
},
methods: {
delCase(item) {
this.$baseConfirm('你确定要删除吗?', null, async() => {
this.delCaseList([item.conversationId])
})
},
delAll() {
this.$baseConfirm('你确定要删除吗?', null, async() => {
this.delCaseList(this.checkedCase)
})
},
async delCaseList(list) {
const res = await conversationDelete(list)
if (res.code === 200) {
this.$baseMessage.success('删除成功!')
this.getList()
}
},
//
onBtnClicked() {
},
//
async getList() {
const res = await conversationList({
pageNum: 1,
pageSize: 99999
})
if (res.code === 200) {
this.caseList = res.data.records
}
},
changeDelFlag() {
this.delFlag = !this.delFlag
},
handleCheckAllChange(val) {
if (val === true) {
const list = []
this.caseList.forEach(e => {
list.push(e.conversationId)
})
this.checkedCase = list
} else {
this.checkedCase = []
}
this.isIndeterminate = false
},
handleCheckedChange(value) {
const checkedCount = value.length
this.checkAll = checkedCount === this.caseList.length
this.isIndeterminate = checkedCount > 0 && checkedCount < this.caseList.length
},
selectCase(item) {
this.$emit('getDetail', item.conversationId, item.caseId)
this.selectId = item.conversationId
}
}
}
</script>
<style lang="scss" scoped>
.historical-records {
min-width: 350px;
background: #F9F9FB;
border-radius: 8px 0px 0px 8px;
padding: 24px;
position: relative;
.empty {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
font-size: 16px;
color: #999999;
margin-top: 200px;
}
.top {
display: flex;font-weight: bold;
font-size: 18px;
color: #1C1F23;
align-items: center;
margin-bottom: 24px;
img {
width: 40px;
height: 40px;
margin-right: 10px;
}
}
.main-new-item {
display: flex;
background: rgba(55,99,255,0.1);
border-radius: 8px 8px 8px 8px;
border: 1px solid #3763FF;
height: 49px;
align-items: center;
padding-left: 16px;
cursor: pointer;
img {
width: 18px;
height: 18px;
}
span {
font-size: 16px;
color: #3763FF;
margin-left: 10px;
}
}
.main-message-item {
display: flex; height: 49px;
align-items: center;
padding-left: 16px;
cursor: pointer;
img {
width: 18px;
height: 18px;
}
span {
font-size: 16px;
color: #333333;
margin-left: 10px;
margin-right: 100px;
}
}
.case-list {
display: flex;
flex-direction: column;
height: calc(100vh - 430px);
overflow: auto;
.case-item {
height: 34px;font-size: 16px;
color: #888888;
margin-left: 25px;
line-height: 34px;
cursor: pointer;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
i {
display: none;
}
}
.actived {
background: #FFFFFF;
font-weight: 400;
font-size: 16px;
color: #333333;
}
.case-item:hover {
background: #EAECF2;
border-radius: 8px 8px 8px 8px;
i {
display: block;
}
}
}
.del-case-list {
display: flex;
flex-direction: column;
height: calc(100vh - 430px);
overflow: auto;
.case-group {
display: flex;
flex-direction: column;
::v-deep {
.el-checkbox {
height: 34px;font-size: 16px;
color: #888888;
display: flex;
align-items: center;
margin-bottom: 16px;
margin-left: 20px;
}
.el-checkbox__label {
font-size: 16px;
}
}
}
}
.footer {
width: 100%;
left: 0;
align-items: center;
height: 72px;
position: absolute;
display: flex;font-size: 16px;
color: #999999;
cursor: pointer;
justify-content: center;
border-top: 1px solid #E0E2E9;
i {
margin-right: 10px;
}
}
.del-footer {
width: 100%;
left: 0;
align-items: center;
height: 72px;
position: absolute;
display: flex;font-size: 16px;
color: #999999;
cursor: pointer;
justify-content: space-around;
border-top: 1px solid #E0E2E9;
.del-item {
font-size: 16px;
color: #FF3429;
cursor: pointer;
i {
margin-right: 10px;
}
}
.logout {
font-size: 16px;
color: #999999;
i {
margin-right: 10px;
}
}
}
}
</style>

@ -1,82 +1,283 @@
<template> <template>
<div class="PoliceAi"> <div class="PoliceAi">
<div class="case-title"> <HistoricalRecords @getDetail="getDetail" />
<div class="case-item"> <div class="PoliceAi-main">
<span>案件名称</span> <div class="case-title">
<span>|</span> <div class="case-item">
<el-select v-model="caseId" style="width: 200px;" clearable placeholder="请选择案件" @change="selectCase"> <span>案件名称</span>
<el-option v-for="item in caseOptions" :key="item.id" :label="item.caseName" :value="item.id" /> <span>|</span>
</el-select> <el-select v-model="caseId" style="width: 200px;" clearable placeholder="请选择案件" @change="selectCase">
<el-option v-for="item in caseOptions" :key="item.id" :label="item.caseName" :value="item.id" />
</el-select>
</div>
<el-input v-model="caseActorName" class="case-input" readonly placeholder="行为人" />
</div>
<div :style="{marginTop:firstEnter?'146px':''}" class="main-content">
<div class="robot">
<div class="robot-top">
<img src="../../assets/police/robot.png" alt="">
<span>数字民警</span>
</div> </div>
<span class="robot-item"> <el-input v-model="caseActorName" class="case-input" readonly placeholder="行为人" />
你好本数字民警可为您提供案件分析结果查询服务您还能通过输入 @来选取特定罪与非罪指标结果以便精准获取您所需信息
</span>
</div> </div>
<div class="nav-list"> <el-scrollbar ref="scrollbar" :style="{marginTop:firstEnter?'146px':''}" class="main-content">
<div class="nav-item">
<div class="nav-item-top"> <div class="robot">
<img src="../../assets/police/analysis.png" alt=""> <div class="robot-top">
<span>案件分析结果</span> <img src="../../assets/police/robot.png" alt="">
<span>数字民警</span>
</div> </div>
<span class="desc">案件分析预测入罪与出罪提示司法判定风险</span> <span class="robot-item">
你好本数字民警可为您提供案件分析结果查询服务您还能通过输入 @来选取特定罪与非罪指标结果以便精准获取您所需信息
</span>
</div> </div>
<div class="nav-item"> <div v-if="navListFlag" class="nav-list">
<div class="nav-item-top"> <div v-for="(item, index) in intentTypeList" :key="index" class="nav-item" @click="selectCaseType(item)">
<img src="../../assets/police/case_info.png" alt=""> <div class="nav-item-top">
<span>案件概况</span> <img v-if="item.type ==='1'" src="../../assets/police/analysis.png" alt="">
<img v-if="item.type ==='2'" src="../../assets/police/case_info.png" alt="">
<img v-if="item.type ==='3'" src="../../assets/police/evidence.png" alt="">
<span>{{ item.name }}</span>
</div>
<span class="desc">{{ item.desc }}</span>
</div> </div>
<span class="desc">获取案件的基本情况概述</span>
</div> </div>
<div class="nav-item"> <div
<div class="nav-item-top"> v-for="(message, index) in conversationList"
<img src="../../assets/police/evidence.png" alt=""> :id="'message' + index"
<span>案件证据指引</span> :key="index"
class="conversation-item"
>
<div v-if="message.role === 'user'" class="user-message">
{{ message.text }}
</div>
<transition name="fade">
<div v-if="message.role === 'robot'" class="robot">
<div class="robot-top">
<img src="../../assets/police/robot.png" alt="">
<span>数字民警</span>
</div>
<div v-if="message.type === '3'">
<div>您好您是要查询案件名称的分析结果吗</div>
<div class="btns">
<div class="btn-item"></div>
<div class="btn-item"></div>
</div>
</div>
<!-- 案件分析结果 -->
<div v-if="message.intentType === '1'" class="robot-item">
<span>您好<span>{{ message.caseName }}</span> 的综合得分为<span :class="['score', message.totalScore >= 70 ? 'success' : 'warning']">{{ `${message.commonScore}+${message.specificCrimeScore}=${message.totalScore}` }}</span>
, 认定<span :class="['score', message.totalScore >= 70 ? 'success' : 'warning']">{{ message.scoreDesc }}</span>
</span>
<span class="robot-message-item">
<span class="point" />
<span>{{ `${message.commonIndexCount}个共性证据指标占${message.commonIndexHitCount}` }}</span>
</span>
<span class="robot-message-item">
<span class="point" />
<span>{{ `${message.specificCrimeIndexCount}${message.specificCrime}${message.specificCrimeIndexHitCount}` }}</span>
</span>
</div>
<!-- 案件概述 案件证据指引 -->
<div v-if="message.intentType === '2' || message.intentType === '3'" class="robot-item">
<span class="robot-message-item">
{{ message.text }}
</span>
</div>
<!-- 指标回答 -->
<div v-if="message.intentType === '0'">
<div class="robot-item index-content">
<span class="index-item">
<span class="label">指标类型</span>
<span class="value">{{ getIndexType(message.indexType) }}</span>
</span>
<span class="index-item">
<span class="label">指标名称</span>
<span class="value">{{ message.indexName }}</span>
</span>
<span class="index-item">
<span class="label">分析结果</span>
<span class="value">{{ message.result }}</span>
</span>
</div>
<div v-if="message.qaSplitList.length > 0 || message.evidenceNames.length > 0" class="collapse" @click="changeShowFlag(message)">
<span>相关笔录及证据</span>
<i class="el-icon-arrow-down" />
</div>
<div v-if="message.showFlag" class="collapse-content">
<div v-if="message.qaSplitList.length > 0" class="title"></div>
<div v-for="(item, index) in message.qaSplitList" :key="index" class="record-item">
<span class="file-name">{{ item.noteRecordName }}</span>
<span>{{ item.answer }}</span>
<span>{{ item.question }}</span>
</div>
<div v-if="message.evidenceNames.length > 0" class="title"></div>
<div class="evidence-list">
<div v-for="(item, index) in message.evidenceNames" :key="index" class="evidence-item">
<span class="file-name" @click="downloadEvidence(item)">{{ item.evidenceName }}</span>
</div>
</div>
</div>
</div>
<!-- dify回答 -->
<div v-if="message.type === '0'">
<div class="robot-item">
<span class="robot-message-item">
{{ message.answer }}
</span>
</div>
<div v-if="message.segmentVOList.length > 0" class="collapse">
<span>相关知识内容</span>
<i class="el-icon-arrow-down" />
</div>
<div v-if="message.segmentVOList.length > 0" class="collapse-content">
<div class="title">涉及文件</div>
<div v-for="(item, index) in message.segmentVOList" :key="index" class="record-item">
<span>{{ item.name }}</span>
<span v-html="item.snippet" />
</div>
</div>
</div>
</div>
</transition>
</div>
</el-scrollbar>
<div class="send-bottom">
<el-input
v-model="sendText"
placeholder="可咨询案件内容、输入@或# 可选择查询指标结果"
@keyup.enter.native="handleSend"
/>
<img src="@/assets/police/send.png" alt="" @click="handleSend">
<div v-if="indexFlag" class="select_index">
<div class="top">
<span v-for="(item, index) in indexTypeList" :key="index" :class="[item.type === activedIndex?'actived':'']" @click="changeType(item)">
{{ item.name }}
</span>
</div>
<el-input
v-model="searchName"
class="top-input"
placeholder="请输入内容"
>
<i slot="prefix" class="el-input__icon el-icon-search" />
</el-input>
<div class="index-list">
<span v-for="(item,index) in showIndexList" :key="index" class="index-list-item" @click="selectIndex(item)">
{{ item.name }}
</span>
</div> </div>
<span class="desc">为补充证据材料信息提供导向</span>
</div> </div>
</div> </div>
</div> </div>
<div class="send-bottom">
<el-input
v-model="sendText"
placeholder="可咨询案件内容、输入@或# 可选择查询指标结果"
@keyup.enter.native="handleSend"
/>
<img src="@/assets/police/send.png" alt="">
</div>
</div> </div>
</template> </template>
<script> <script>
import { queryCaseList, robotChat } from '@/api/caseManagement' import { queryCaseList, robotChat, conversationInfoList } from '@/api/caseManagement'
import { queryIndexData } from '@/api/indexRule' import { queryIndexData } from '@/api/indexRule'
import { marked } from 'marked' import HistoricalRecords from './HistoricalRecords.vue'
import { baseURL } from '@/config'
import { downloadEvidence } from '@/api/config/uploadApi'
export default { export default {
name: 'PoliceAi', name: 'PoliceAi',
components: {
HistoricalRecords
},
data() { data() {
return { return {
caseId: '', caseId: '',
caseActorName: '', caseActorName: '',
// //
firstEnter: true, firstEnter: true,
navListFlag: true,
sendText: '', sendText: '',
indexFlag: false,
conversationId: '',
conversationList: [], conversationList: [],
indexTypeList: [
{
name: '共性指标',
type: '1'
},
{
name: '入罪指标',
type: '2'
},
{
name: '出罪指标',
type: '3'
}
],
activedIndex: '1',
indexList: [],
showIndexList: [], //
intentTypeList: [
{
name: '案件分析结果',
type: '1',
desc: '案件分析预测入罪与出罪,提示司法判定风险'
},
{
name: '案件概况',
type: '2',
desc: '获取案件的基本情况概述'
},
{
name: '案件证据指引',
type: '3',
desc: '为补充证据材料信息提供导向'
}
],
searchName: '',
caseOptions: [] caseOptions: []
} }
}, },
mounted() { watch: {
sendText(val) {
if (val === '@') {
this.indexFlag = true
this.activedIndex = '1'
this.getIndexData('1')
} else {
this.indexFlag = false
}
},
searchName(val) {
if (val) {
const list = this.filterByProperty(this.indexList, 'name', val)
this.showIndexList = list
} else {
this.showIndexList = this.indexList
}
}
},
mounted() {
this.fetchData()
}, },
methods: { methods: {
//
async getDetail(id, caseId) {
this.caseId = caseId
this.selectCase(this.caseId)
this.conversationList = []
this.conversationId = id
const res = await conversationInfoList({
conversationId: this.conversationId,
pageNum: 1,
pageSize: 99999
})
if (res.code === 200) {
for (const item of res.data.records) {
this.conversationList.push({
role: 'user',
text: item.question
})
this.getAnswerContent(item)
}
}
},
// //
fetchData() { fetchData() {
queryCaseList({}, 1, 99999).then(res => { queryCaseList({}, 1, 99999).then(res => {
@ -88,14 +289,165 @@ export default {
queryIndexData({ queryIndexData({
indexType: val indexType: val
}, 1, 9999).then(res => { }, 1, 9999).then(res => {
this.questionlist = res.data.result this.indexList = res.data.result
this.showIndexList = res.data.result
}) })
}, },
selectCase() { //
changeType(item) {
this.activedIndex = item.type
this.getIndexData(item.type)
this.searchName = ''
},
selectCase(val) {
const obj = this.caseOptions.find(item => item.id === val)
this.caseActorName = obj.caseActorName
},
selectCaseType(item) {
if (!this.caseId) {
this.$baseMessage.error('请选择案件!')
return
}
this.conversationList.push({
role: 'user',
text: item.name
})
this.navListFlag = false
this.chat({
caseId: this.caseId,
conversationId: this.conversationId,
query: '',
type: '1',
intentType: item.type
})
},
//
filterByProperty(arr, key, searchString) {
return arr.filter(obj =>
obj[key] && obj[key].toString().toLowerCase().includes(searchString.toLowerCase())
)
},
downloadFile(url, fileName) {
const link = document.createElement('a')
link.href = url
link.download = fileName
link.click()
},
//
downloadEvidence(item) {
this.downloadFile(`${baseURL}${downloadEvidence}${item.evidenceId}`, item.evidenceName)
},
//
selectIndex(item) {
this.indexFlag = false
this.searchName = ''
this.conversationList.push({
role: 'user',
text: item.name
})
this.chat({
caseId: this.caseId,
query: item.name,
conversationId: this.conversationId,
type: '1',
intentType: '0'
})
},
chat(obj) {
robotChat(obj).then(res => {
if (res.code === 200) {
this.conversationId = res.data.conversationId
this.getAnswerContent(res.data)
}
})
},
//
getAnswerContent(data) {
if (data.intentType === '1') {
this.conversationList.push({
...data.answwerMap,
role: 'robot',
intentType: data.intentType
})
} else if (data.intentType === '2') {
this.conversationList.push({
role: 'robot',
intentType: data.intentType,
text: data.answwerMap.answerText
})
} else if (data.intentType === '3') {
this.conversationList.push({
role: 'robot',
intentType: data.intentType,
text: data.answwerMap.guideDesc
})
//
} else if (data.intentType === '0') {
this.conversationList.push({
role: 'robot',
intentType: data.intentType,
...data.answwerMap
})
}
// dify
if (data.type === '0') {
this.conversationList.push({
role: 'robot',
answer: data.answer,
type: data.type,
segmentVOList: data.segmentVOList
})
}
this.$nextTick(() => {
this.scrollToBottom()
})
},
//
getIndexType(val) {
for (const item of this.indexTypeList) {
if (val === item.type) {
return item.name
}
}
},
//
changeShowFlag(item) {
if (item.showFlag === true) {
this.$set(item, 'showFlag', false)
} else {
this.$set(item, 'showFlag', true)
}
},
scrollToBottom() {
const scrollbar = this.$refs.scrollbar
if (scrollbar) {
scrollbar.wrap.scrollTo(0, scrollbar.wrap.scrollHeight)
}
}, },
handleSend() { handleSend() {
if (!this.caseId) {
this.$baseMessage.error('请选择案件!')
return
}
if (!this.sendText) {
this.$baseMessage.error('请输入内容!')
return
}
this.sendText = ''
this.conversationList.push({
role: 'user',
text: this.sendText
})
this.scrollToBottom()
this.chat({
caseId: this.caseId,
query: this.sendText,
conversationId: this.conversationId,
type: '0',
intentType: ''
})
} }
} }
} }
@ -107,9 +459,12 @@ export default {
position: relative; position: relative;
padding-top: 24px; padding-top: 24px;
display: flex; display: flex;
flex-direction: column; .PoliceAi-main {
align-items: center; display: flex;
.case-title { flex-direction: column;
align-items: center;
flex: 1;
.case-title {
width: 632px; width: 632px;
height: 98px; height: 98px;
background: rgba(55,99,255,0.15); background: rgba(55,99,255,0.15);
@ -154,8 +509,10 @@ export default {
} }
.main-content { .main-content {
flex: 1; flex: 1;
overflow: auto; overflow-y: auto;
width: 1154px; width: 1154px;
position: relative;
.robot { .robot {
.robot-top { .robot-top {
display: flex; display: flex;
@ -175,21 +532,112 @@ export default {
background: #F5F7FF; background: #F5F7FF;
border-radius: 16px 0px 16px 16px; border-radius: 16px 0px 16px 16px;
line-height: 53px;font-size: 16px; line-height: 28px;font-size: 16px;
color: #333333; color: #333333;
padding: 16px; padding: 16px;
margin-bottom: 16px; margin-bottom: 16px;
display: flex;
flex-direction: column;
.success {
color: #00975E;
font-weight: bold;
}
.warning {
color: rgba(255, 147, 17, 1);
font-weight: bold;
}
.robot-message-item {
display: flex;
align-items: center;
.point {
width: 5px;
height: 5px;
background-color: black;
border-radius: 50%;
margin: 0 10px;
}
}
}
.index-content {
display: flex;
flex-direction: column;
.index-item {
display: flex;
margin-bottom: 16px;
.label {
font-weight: bold;
font-size: 16px;
color: #333333;
margin-right: 10px;
}
.value {
font-size: 16px;
color: #333333;
}
}
}
.collapse {
width: 198px;
padding: 10px 16px;
background: #F6F7F9;
border-radius: 6px 6px 6px 6px;
font-size: 16px;
display: flex;
color: #666666;
justify-content: space-between;
margin-bottom: 8px;
cursor: pointer;
}
.collapse-content {
padding: 16px;
background: #F6F7F9;
border-radius: 6px 6px 6px 6px;
.title {
font-size: 16px;
color: #333333;
margin-bottom: 8px;
}
.record-item {
margin-bottom: 16px;
display: flex;
flex-direction: column;font-size: 16px;
color: #333333;
line-height: 28px;
.file-name {
font-size: 16px;
color: #3763FF;
cursor: pointer;
margin-bottom: 8px;
}
}
.evidence-list {
display: flex;
.evidence-item {
font-size: 16px;
color: #3763FF;
cursor: pointer;
margin-bottom: 8px;
margin-right: 8px;
}
}
} }
} }
.user-message {
margin: 24px 0;
text-align: right;font-size: 16px;
color: #333333;
}
.nav-list { .nav-list {
display: flex; display: flex;
margin-top: 16px; margin-top: 16px;
margin-bottom: 16px;
.nav-item { .nav-item {
background: #FFFFFF; background: #FFFFFF;
border-radius: 8px 8px 8px 8px; border-radius: 8px 8px 8px 8px;
border: 1px solid #D9D9D9; border: 1px solid #D9D9D9;
padding: 24px; padding: 24px;
margin-right: 24px; margin-right: 24px;
cursor: pointer;
.desc { .desc {
font-size: 14px; font-size: 14px;
color: #999999; color: #999999;
@ -206,10 +654,15 @@ export default {
} }
} }
} }
} }
.main-content::-webkit-scrollbar {
// display: none; /* Chrome, Safari Opera */
}
.send-bottom { .send-bottom {
width: 1154px; width: 1154px;
height: 75px; height: 75px;
position: relative;
background: #FFFFFF; background: #FFFFFF;
border-radius: 16px 16px 16px 16px; border-radius: 16px 16px 16px 16px;
border: 2px solid rgba(55, 99, 255, 1); border: 2px solid rgba(55, 99, 255, 1);
@ -232,7 +685,69 @@ export default {
top: 12px; top: 12px;
cursor: pointer; cursor: pointer;
} }
.select_index {
position: absolute;
bottom: 77px;
left: 12px;
width: 1132px;
height: 424px;
background: #FFFFFF;
box-shadow: 0px 0px 8px 0px rgba(0,0,0,0.15);
border-radius: 6px 6px 6px 6px;
.top {
height: 62px;
display: flex;
border-bottom: 1px solid #EAEAEA;
align-items: center;
padding-left: 24px;
span {
font-size: 16px;
height: 62px;
line-height: 62px;
color: #999999;
margin-right: 40px;
cursor: pointer;
}
.actived {
color: #3763FF;
border-bottom: 3px solid #3763FF;
}
}
.top-input {
width: 1000px;
border-radius: 6px 6px 6px 6px;
border: 1.4px solid #3763FF;
margin-top: 24px;
margin: 24px;
}
.index-list {
display: flex;
flex-direction: column;
overflow: auto;
padding-left: 24px;
height: 260px;
.index-list-item {
font-weight: 400;
font-size: 16px;
color: #333333;
cursor: pointer;
margin-bottom: 24px;
}
}
}
} }
}
} }
</style> </style>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>

@ -7,8 +7,8 @@
--> -->
<template> <template>
<div class="CaseAtlas"> <div id="chartsMax" class="CaseAtlas">
<div class="left"> <div class="left" :style="{margin:fullFlag?'24px 0 0 24px':''}">
<div class="title">{{ `实体(${nodeLabels.length})` }}</div> <div class="title">{{ `实体(${nodeLabels.length})` }}</div>
<div class="node-list"> <div class="node-list">
<span v-for="(item,index) in nodeLabels" :key="index" :class="[item.selected === true?'actived':'']" class="node-item" @click="selectItem(item)">{{ item.name }}</span> <span v-for="(item,index) in nodeLabels" :key="index" :class="[item.selected === true?'actived':'']" class="node-item" @click="selectItem(item)">{{ item.name }}</span>
@ -31,7 +31,7 @@
<div class="btn" @click="search"></div> <div class="btn" @click="search"></div>
</div> </div>
</div> </div>
<vue-charts id="chartsMax" autoresize :style="{ width: '100%', height: '100%' }" :option="caseAtlasOption" /> <vue-charts autoresize :style="{ width: '100%', height: '100%' }" :option="caseAtlasOption" />
<!-- <div class="full_screen" id="fullScreen" v-if="isFullScreen"> <!-- <div class="full_screen" id="fullScreen" v-if="isFullScreen">
</div> --> </div> -->
</div> </div>

@ -45,7 +45,8 @@
</template> </template>
<template #percentage="{row}"> <template #percentage="{row}">
<div class="per-content"> <div class="per-content">
<span>{{ row.rowPercentage + '%' }}</span> <span v-if="row.rowPercentage !== null">{{ row.rowPercentage + '%' }}</span>
<span v-else>{{ row.percentage }}</span>
<el-badge v-if="row.isPromptUpdate" style="margin-left: 6px;"> <el-badge v-if="row.isPromptUpdate" style="margin-left: 6px;">
<el-tag type="success">最新</el-tag> <el-tag type="success">最新</el-tag>
</el-badge> </el-badge>
@ -181,7 +182,7 @@ export default {
}, },
// //
handleCreateAtlas(row) { handleCreateAtlas(row) {
if (row.percentage === '未提取') { if (row.rowPercentage === '未提取') {
this.$baseMessage.error('请先操作笔录提取') this.$baseMessage.error('请先操作笔录提取')
return return
} }

@ -218,7 +218,7 @@ export default {
// //
this.isEdit = this.$route.query.isEdit === '1' this.isEdit = this.$route.query.isEdit === '1'
this.fetchData() this.fetchData()
this.queryCaseScore()
}, },
methods: { methods: {
// node // node
@ -271,6 +271,7 @@ export default {
}, },
// //
fetchData() { fetchData() {
this.queryCaseScore()
queryCaseList({ id: this.$route.params['id'] }, 1, 1).then(res => { queryCaseList({ id: this.$route.params['id'] }, 1, 1).then(res => {
if (res.code === 200) { if (res.code === 200) {
this.caseData = res.data.records[0] this.caseData = res.data.records[0]

@ -37,7 +37,7 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item v-if="dataInfo.type ==='1'" label="提取属性" prop="extractAttributes"> <el-form-item v-if="dataInfo.type ==='1' && dataInfo.extractAttributes && dataInfo.extractAttributes.length > 0" label="提取属性" prop="extractAttributes">
<div class="params-table"> <div class="params-table">
<div class="top"> <div class="top">
<span style="width: 450px;">属性键值</span> <span style="width: 450px;">属性键值</span>
@ -47,20 +47,20 @@
<div class="params-table-content"> <div class="params-table-content">
<vuedraggable v-model="dataInfo.extractAttributes" animation="400" class="file-list"> <vuedraggable v-model="dataInfo.extractAttributes" animation="400" class="file-list">
<div v-for="(item,index) in dataInfo.extractAttributes" :key="index" class="table-item"> <div v-for="(item,index) in dataInfo.extractAttributes" :key="index" class="table-item">
<el-input v-model="item.attrName" style="width: 400px;margin-right: 40px;" placeholder="请输入" /> <el-input v-model="item.attrName" readonly style="width: 400px;margin-right: 40px;" placeholder="请输入" />
<el-select v-model="item.attrValueType" style="width: 120px;margin-right: 40px;" clearable placeholder="请选择"> <el-select v-model="item.attrValueType" disabled style="width: 120px;margin-right: 40px;" clearable placeholder="请选择">
<el-option v-for="items in extractList" :key="items.value" :label="items.label" :value="items.value" /> <el-option v-for="items in extractList" :key="items.value" :label="items.label" :value="items.value" />
</el-select> </el-select>
<i class="el-icon-delete" @click="delItem(index)" /> <!-- <i class="el-icon-delete" @click="delItem(index)" /> -->
</div> </div>
</vuedraggable> </vuedraggable>
</div> </div>
<div class="add-table" @click="addItem"> <!-- <div class="add-table" @click="addItem">
<i class="el-icon-circle-plus-outline" style="color: #3763FF;font-size: 16px;" /> <i class="el-icon-circle-plus-outline" style="color: #3763FF;font-size: 16px;" />
<span>添加数据</span> <span>添加数据</span>
</div> </div> -->
</div> </div>
</el-form-item> </el-form-item>
<el-form-item v-if="dataInfo.type ==='2'" label="参数配置"> <el-form-item v-if="dataInfo.type ==='2'" label="参数配置">
@ -185,8 +185,8 @@ export default {
type: [{ required: true, message: '提示词类型不能为空!', trigger: 'change' }], type: [{ required: true, message: '提示词类型不能为空!', trigger: 'change' }],
name: [{ required: true, message: '提示词名称不能为空!', trigger: 'change' }], name: [{ required: true, message: '提示词名称不能为空!', trigger: 'change' }],
typeList: [{ required: true, message: '分类不能为空!', trigger: 'change' }], typeList: [{ required: true, message: '分类不能为空!', trigger: 'change' }],
evidenceCategoryIdList: [{ required: true, message: '所属目录不能为空!', trigger: 'change' }], evidenceCategoryIdList: [{ required: true, message: '所属目录不能为空!', trigger: 'change' }]
extractAttributes: [{ required: true, message: '提取属性不能为空!', trigger: 'change' }] // extractAttributes: [{ required: true, message: '!', trigger: 'change' }]
}, },
defaultProps: { defaultProps: {
children: 'child', children: 'child',
@ -349,12 +349,12 @@ export default {
this.$refs.form.validate(valid => { this.$refs.form.validate(valid => {
if (valid) { if (valid) {
if (this.dataInfo.type === '1') { if (this.dataInfo.type === '1') {
for (const item of this.dataInfo.extractAttributes) { // for (const item of this.dataInfo.extractAttributes) {
if (item.attrName === '' || item.attrValueType === '') { // if (item.attrName === '' || item.attrValueType === '') {
this.$baseMessage.error('请填写完整属性') // this.$baseMessage.error('')
return // return
} // }
} // }
if (this.hasDuplicateValue(this.dataInfo.extractAttributes, 'attrName')) { if (this.hasDuplicateValue(this.dataInfo.extractAttributes, 'attrName')) {
this.$baseMessage.error('属性键值重复') this.$baseMessage.error('属性键值重复')
return return
@ -525,11 +525,11 @@ export default {
// padding: 16px; // padding: 16px;
::v-deep { ::v-deep {
.el-textarea__inner { .el-textarea__inner {
border: none; border: none;
resize: none; resize: none;
} }
} }
} }
} }
} }

Loading…
Cancel
Save