Compare commits

...

10 Commits

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@ -0,0 +1,41 @@
<template>
<img :src="imageUrl" @click="$emit('click')">
</template>
<script>
import request from '@/utils/request'
export default {
name: 'BCTokenImage',
props: {
src: String
},
data() {
return {
imageUrl: '' //
}
},
watch: {
src: {
handler(value) {
this.loadImage(value)
},
immediate: true
}
},
methods: {
loadImage(url) {
console.log('111', url)
request({
method: 'get',
responseType: 'blob', // blob
url
}).then(response => {
// URL使
this.imageUrl = URL.createObjectURL(new Blob([response]))
}).catch(error => {
console.error(`BCTokenImage error: ${url}加载失败!`, error)
})
}
}
}
</script>

@ -5,7 +5,7 @@ const network = {
// 默认的接口地址 如果是开发环境和生产环境走vab-mock-server当然你也可以选择自己配置成需要的接口地址
baseURL:
process.env.NODE_ENV === 'development'
? 'http://192.168.10.142:8097/fu-hsi-server'
? 'http://192.168.10.138:9978/fu-hsi-server'
: '/fuHsiApi',
// 配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8
contentType: 'application/json;charset=UTF-8',

@ -87,7 +87,7 @@ export default {
.app-main-container {
height: $base-app-main-height;
position: relative;
overflow: hidden;
overflow: auto;
//padding: 10px;
margin: 0 2%;
box-sizing: border-box;

@ -7,33 +7,87 @@
-->
<template>
<div>
<div v-if="!isActived" class="HoverButton" @click="getList">
<el-popover
placement="left"
width="240"
trigger="click"
>
<div class="HoverButton-main">
<div class="main-new-item" @click="onBtnClicked">
<img src="@/assets/common/new.png" alt="">
<span>新对话</span>
</div>
<div class="main-message-item">
<img src="@/assets/common/message.png" alt="">
<span>最近对话</span>
<!-- <i class="el-icon-arrow-down el-icon--right" /> -->
</div>
<div class="case-list">
<span :title="item.caseName " v-for="(item,index) in caseList" :key="index" class="case-item" @click="openPage(item)">{{ item.caseName }}</span>
</div>
</div>
<div
ref="floatButton"
slot="reference"
class="float_info"
@click="onBtnClicked"
/>
</el-popover>
<!--对话弹窗-->
<conversation-dialog ref="conversion"/>
<conversation-dialog ref="conversion" />
</div>
</template>
<script>
import store from '@/store'
import { conversationList } from '@/api/caseManagement'
export default {
name: 'HoverButton',
data() {
return {
caseList: [
]
}
},
computed: {
isActived() {
return this.$route.path === '/policeAi'
}
},
mounted() {
this.getList()
},
methods: {
onBtnClicked() {
this.$refs.conversion.show()
store.dispatch('user/setConversationId', 'addNew')
this.$router.push({
path: '/policeAi'
})
},
//
async getList() {
const res = await conversationList({
pageNum: 1,
pageSize: 99999
})
if (res.code === 200) {
this.caseList = res.data.records.splice(0, 3)
}
},
openPage(item) {
store.dispatch('user/setConversationId', item.conversationId)
this.$router.push({
path: '/policeAi'
})
}
}
}
</script>
<style lang="scss" scoped>
.float_info {
.HoverButton {
.float_info {
position: fixed;
bottom: 120px;
right: 2%;
@ -45,6 +99,62 @@ export default {
cursor: pointer;
background: url("~@/assets/home/anjianzhushou@2x.png") center no-repeat;
background-size: 100% 100%;
}
}
.HoverButton-main {
// padding: 16px;
.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;
.case-item {
height: 34px;font-size: 14px;
color: #666666;
padding-left: 45px;
line-height: 34px;
cursor: pointer;
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.case-item:hover {
background: #F5F5F5;
}
}
}
</style>

@ -2,13 +2,14 @@ import Vue from 'vue'
import App from './App'
import store from './store'
import router from './router'
import BCTokenImage from '@/components/BCTokenImage'
import './plugins'
import '@/layouts/export'
// // 解决滚动背景的问题
// import 'default-passive-events'
import appInit from './data/appInit'
Vue.config.productionTip = false
Vue.component('BCTokenImage', BCTokenImage) // 全局注册
new Vue({
el: '#app',
router,

@ -19,6 +19,7 @@ const state = () => ({
endTime: null,
avatar: null,
adminFlag: '',
conversationId: '',
permissions: []
})
const getters = {
@ -31,7 +32,8 @@ const getters = {
userId: (state) => state.userId,
unitId: (state) => state.unitId,
adminFlag: (state) => state.adminFlag,
permissions: (state) => state.permissions
permissions: (state) => state.permissions,
conversationId: (state) => state.conversationId
}
const mutations = {
setAccessToken(state, accessToken) {
@ -67,13 +69,18 @@ const mutations = {
},
setPermissions(state, permissions) {
state.permissions = permissions
},
setConversationId(state, conversationId) {
state.conversationId = conversationId
}
}
const actions = {
setPermissions({ commit }, permissions) {
commit('setPermissions', permissions)
},
setConversationId({ commit }, conversationId) {
commit('setConversationId', conversationId)
},
async login({ commit }, userInfo) {
const { userAccount, password } = userInfo
const { data } = await login({

@ -12,6 +12,7 @@
* @param cFormat
* @returns {string|null}
*/
import request from '@/utils/request'
export function parseTime(time, cFormat) {
if (!time) return '-'
if (arguments.length === 0) {
@ -249,3 +250,17 @@ export function zeroFill(num, length) {
}
return num
}
// 预览图片加token
export function getPreviewWithToken(url) {
request({
method: 'get',
responseType: 'blob', // 重要设置响应类型为blob
url
}).then(response => {
// 创建一个URL浏览器可以使用它来加载图片
return URL.createObjectURL(new Blob([response]))
}).catch(error => {
console.error(`BCTokenImage error: ${url}加载失败!`, error)
})
}

@ -43,6 +43,7 @@ const handleCode = (code, msg) => {
const instance = axios.create({
baseURL,
timeout: requestTimeout,
withCredentials: true,
headers: {
'Content-Type': contentType,
'X-Frame-Options': 'SAMEORIGIN',

@ -3,7 +3,7 @@
<div class="historical-records">
<div class="top">
<img src="../../assets/police/robot.png" alt="">
<span>伏小羲</span>
<span>数字民警</span>
</div>
<div class="main-new-item" @click="onBtnClicked">
<img src="@/assets/common/new.png" alt="">
@ -16,7 +16,8 @@
</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>
<span class="date">{{ item.createDay }}</span>
<span class="name" :title="item.caseName">{{ item.caseName }}</span>
<i class="el-icon-delete file-delete" @click.stop="delCase(item)" />
</span>
</div>
@ -65,9 +66,23 @@ export default {
showCaseList: []
}
},
// computed: {
// ...mapGetters({
// testConversationId: 'user/conversationId'
// })
// },
mounted() {
this.getList()
},
activated() {
if (this.$store.state.user.conversationId === 'addNew') {
this.$emit('addNew')
this.selectId = ''
this.$store.state.user.conversationId = ''
} else {
this.getList()
}
},
methods: {
delCase(item) {
this.$baseConfirm('你确定要删除吗?', null, async() => {
@ -75,11 +90,20 @@ export default {
})
},
delAll() {
if (this.checkedCase.length === 0) {
this.$baseMessage.error('请选择要删除的对话')
return
}
this.$baseConfirm('你确定要删除吗?', null, async() => {
this.changeDelFlag()
this.delCaseList(this.checkedCase)
})
},
async delCaseList(list) {
const hasValue = list.indexOf(this.selectId) !== -1
if (hasValue) {
this.$emit('addNew')
}
const res = await conversationDelete(list)
if (res.code === 200) {
this.$baseMessage.success('删除成功!')
@ -88,16 +112,29 @@ export default {
},
//
onBtnClicked() {
this.$emit('addNew')
this.selectId = ''
},
//
async getList() {
async getList(id) {
const res = await conversationList({
pageNum: 1,
pageSize: 99999
})
if (res.code === 200) {
this.caseList = res.data.records
if (this.$store.state.user.conversationId) {
this.selectId = this.$store.state.user.conversationId
for (const item of this.caseList) {
if (item.conversationId === this.$store.state.user.conversationId) {
this.selectCase(item)
}
}
this.$store.state.user.conversationId = ''
}
if (id) {
this.selectId = id
}
}
},
changeDelFlag() {
@ -194,18 +231,30 @@ export default {
.case-list {
display: flex;
flex-direction: column;
height: calc(100vh - 430px);
height: calc(100vh - 408px);
overflow: auto;
.case-item {
height: 34px;font-size: 16px;
color: #888888;
margin-left: 25px;
// margin-left: 25px;
line-height: 34px;
cursor: pointer;
padding: 0 20px;
padding: 0 20px 0 12px;
display: flex;
align-items: center;
justify-content: space-between;
// justify-content: space-between;
border-radius: 8px 8px 8px 8px;
.name {
width: 240px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.date {
font-size: 12px;
color: #666666;
margin-right: 8px;
}
margin-bottom: 16px;
i {
display: none;
@ -216,6 +265,11 @@ export default {
font-weight: 400;
font-size: 16px;
color: #333333;
border-radius: 8px 8px 8px 8px;
font-weight: 600;
.date {
color: #333333;
}
}
.case-item:hover {
background: #EAECF2;
@ -278,6 +332,7 @@ export default {
font-size: 16px;
color: #FF3429;
cursor: pointer;
margin-left: 148px;
i {
margin-right: 10px;
}

@ -1,24 +1,24 @@
<template>
<div class="PoliceAi">
<HistoricalRecords @getDetail="getDetail" />
<HistoricalRecords v-if="caseOptions.length > 0" ref="HistoricalRecordsRef" @getDetail="getDetail" @addNew="addNew" />
<div class="PoliceAi-main">
<div class="case-title">
<div v-if="!conversationId" class="case-title">
<div class="case-item">
<span>案件名称</span>
<span>|</span>
<el-select v-model="caseId" style="width: 200px;" clearable placeholder="请选择案件" @change="selectCase">
<el-select v-model="caseId" filterable :disabled="conversationId !==''" 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>
<el-scrollbar ref="scrollbar" :style="{marginTop:firstEnter?'146px':''}" class="main-content">
<div ref="scrollbar" :style="{marginTop:!conversationId?'110px':'0px'}" class="main-content" @scroll="handleScroll">
<div class="robot">
<div class="robot-top">
<img src="../../assets/police/robot.png" alt="">
<span>数字民警</span>
<span>伏小羲</span>
</div>
<span class="robot-item">
你好本数字民警可为您提供案件分析结果查询服务您还能通过输入 @来选取特定罪与非罪指标结果以便精准获取您所需信息
@ -48,15 +48,11 @@
<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>
<span>伏小羲</span>
</div>
<div v-if="index !== conversationList.length -1 || !loading">
<!-- 不询问 -->
<div v-if="message.dialogueCount !== 1 ">
<!-- 案件分析结果 -->
<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>
@ -77,12 +73,14 @@
{{ message.text }}
</span>
</div>
</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 :title="getIndexType(message.indexType)" class="value">{{ getIndexType(message.indexType) }}</span>
</span>
<span class="index-item">
<span class="label">指标名称</span>
@ -95,12 +93,13 @@
</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" />
<i v-if="!message.showFlag" class="el-icon-arrow-down" />
<i v-if="message.showFlag" class="el-icon-arrow-up" />
</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 class="file-name" @click="downloadRecord(item)">{{ item.noteName }}</span>
<span>{{ item.answer }}</span>
<span>{{ item.question }}</span>
</div>
@ -113,40 +112,61 @@
</div>
</div>
<!-- dify回答 -->
<div v-if="message.type === '0'">
<div class="robot-item">
<div v-if="message.type === '0' ">
<div v-if="message.answer" class="robot-item">
<span class="robot-message-item">
{{ message.answer }}
</span>
<div v-if="message.askFlag && message.intentType && message.intentType!=='0'" class="btns">
<div class="btn-item" @click="selectAskItem(message,'是')"></div>
<div class="btn-item" @click="selectAskItem(message,'否')"></div>
</div>
</div>
<div v-if="message.segmentVOList.length > 0" class="collapse">
<div v-if="message.segmentList && message.segmentList.length > 0" class="collapse" @click="changeShowFlag(message)">
<span>相关知识内容</span>
<i class="el-icon-arrow-down" />
<i v-if="!message.showFlag" class="el-icon-arrow-down" />
<i v-if="message.showFlag" class="el-icon-arrow-up" />
</div>
<div v-if="message.segmentVOList.length > 0" class="collapse-content">
<div v-if="message.segmentList && message.segmentList.length > 0 && message.showFlag" class="collapse-content">
<div class="title">涉及文件</div>
<div v-for="(item, index) in message.segmentVOList" :key="index" class="record-item">
<span>{{ item.name }}</span>
<div v-for="(item, index) in message.segmentList" :key="index" class="record-item">
<span style="color: #333333;cursor: unset;" class="file-name ">{{ item.name }}</span>
<span v-html="item.snippet" />
</div>
</div>
</div>
<!-- 指标询问选项 -->
<div v-if="message.adviceList && message.askFlag " class="option-list">
<span v-for="(item, index) in message.adviceList" :key="index" class="option-item" @click="selectAskIndex(message,item.indexName)">
<span class="name">{{ `${item.indexType} ${item.indexType?'|':''} ${item.indexName}` }}</span>
<i class="el-icon-arrow-right" />
</span>
</div>
</div>
<!-- <div v-if="!message.adviceList && message.askFlag ">
</div> -->
<div v-else class="loading">
<img src="../../assets/common/loading.gif" alt="">
<span>模型正在生成结果....</span>
</div>
</div>
</transition>
</div>
</el-scrollbar>
</div>
<div class="send-bottom">
<el-input
v-model="sendText"
placeholder="可咨询案件内容、输入@或# 可选择查询指标结果"
:readonly="!caseId"
placeholder="可咨询案件内容、输入@可选择查询指标结果"
@keyup.enter.native="handleSend"
/>
<img src="@/assets/police/send.png" alt="" @click="handleSend">
<img v-if="!loading" class="input-img" src="@/assets/police/send.png" alt="" @click="handleSend">
<img v-if="loading" class="input-img" src="@/assets/police/pause.png" alt="">
<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)">
@ -155,18 +175,23 @@
</div>
<el-input
ref="myInput"
v-model="searchName"
maxlength="50"
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)">
<span v-for="(item,index) in showIndexList" :key="index" class="index-list-item" @click="selectIndex(item.name)">
{{ item.name }}
</span>
</div>
</div>
<div v-if="isShowDownIcon" class="scroll-icon" @click="scrollToBottom">
<img src="../../assets/police/down.png" alt="">
</div>
</div>
</div>
@ -178,7 +203,7 @@ import { queryCaseList, robotChat, conversationInfoList } from '@/api/caseManage
import { queryIndexData } from '@/api/indexRule'
import HistoricalRecords from './HistoricalRecords.vue'
import { baseURL } from '@/config'
import { downloadEvidence } from '@/api/config/uploadApi'
import { downloadEvidence, commonDownloadFile } from '@/api/config/uploadApi'
export default {
name: 'PoliceAi',
components: {
@ -193,6 +218,7 @@ export default {
navListFlag: true,
sendText: '',
indexFlag: false,
loading: false,
conversationId: '',
conversationList: [],
indexTypeList: [
@ -210,6 +236,8 @@ export default {
}
],
activedIndex: '1',
// down icon
isShowDownIcon: false,
indexList: [],
showIndexList: [], //
intentTypeList: [
@ -230,6 +258,7 @@ export default {
}
],
searchName: '',
distanceToBottom: 0,
caseOptions: []
}
},
@ -239,6 +268,10 @@ export default {
this.indexFlag = true
this.activedIndex = '1'
this.getIndexData('1')
this.$nextTick(() => {
const inputElement = this.$refs.myInput.$el.querySelector('input')
inputElement.focus()
})
} else {
this.indexFlag = false
}
@ -259,6 +292,7 @@ export default {
methods: {
//
async getDetail(id, caseId) {
this.loading = false
this.caseId = caseId
this.selectCase(this.caseId)
this.conversationList = []
@ -275,9 +309,18 @@ export default {
text: item.question
})
this.getAnswerContent(item)
this.navListFlag = false
}
}
},
//
addNew() {
this.caseId = ''
this.conversationId = ''
this.caseActorName = ''
this.conversationList = []
this.navListFlag = true
},
//
fetchData() {
queryCaseList({}, 1, 99999).then(res => {
@ -304,6 +347,7 @@ export default {
this.caseActorName = obj.caseActorName
},
selectCaseType(item) {
if (this.loading) return
if (!this.caseId) {
this.$baseMessage.error('请选择案件!')
return
@ -316,7 +360,7 @@ export default {
this.chat({
caseId: this.caseId,
conversationId: this.conversationId,
query: '',
query: item.name,
type: '1',
intentType: item.type
})
@ -335,61 +379,128 @@ export default {
},
//
downloadEvidence(item) {
console.log('baseURL', baseURL)
this.downloadFile(`${baseURL}${downloadEvidence}${item.evidenceId}`, item.evidenceName)
},
//
downloadRecord(item) {
// const fileId = item.fileIds.split(',')[0]
this.downloadFile(`${baseURL}${commonDownloadFile}${item.noteFileId}`, item.noteName)
},
//
selectAskIndex(item, name) {
this.$set(item, 'askFlag', false)
this.selectIndex(name, name === '以上都不是' ? 'none' : '', item.dialogueCount)
},
//
selectAskItem(item, val) {
this.$set(item, 'askFlag', false)
if (this.loading) return
this.indexFlag = false
this.searchName = ''
this.conversationList.push({
role: 'user',
text: val
})
this.sendText = ''
this.chat({
caseId: this.caseId,
query: val,
conversationId: this.conversationId,
dialogueCount: item.dialogueCount,
type: '0',
intentType: item.intentType
})
},
//
selectIndex(item) {
selectIndex(name, val, dialogueCount) {
if (this.loading) return
this.indexFlag = false
this.searchName = ''
this.conversationList.push({
role: 'user',
text: item.name
text: name
})
this.sendText = ''
this.chat({
caseId: this.caseId,
query: item.name,
query: name,
dialogueCount,
conversationId: this.conversationId,
type: '1',
intentType: '0'
type: val === 'none' ? '0' : '1',
intentType: val === 'none' ? '' : '0'
})
},
chat(obj) {
this.loading = true
this.conversationList.push({
role: 'robot'
})
this.scrollToBottom()
robotChat(obj).then(res => {
this.conversationList.splice(this.conversationList.length - 1, 1)
if (res.code === 200) {
if (this.conversationId !== res.data.conversationId) {
this.$refs.HistoricalRecordsRef.getList(res.data.conversationId)
}
this.conversationId = res.data.conversationId
this.getAnswerContent(res.data)
this.getAnswerContent(res.data, 'add')
}
}).catch(() => {
//
this.loading = false
this.conversationList.splice(this.conversationList.length - 1, 1)
this.conversationList.push({
role: 'robot',
intentType: '2',
text: '抱歉,我可能没理解清楚。如需进一步咨询,请明确您的问题。同时,输入“@”可选取特定指标结果,以便精准获取信息。'
})
})
},
//
getAnswerContent(data) {
getAnswerContent(data, type) {
//
if (data.dialogueCount === 1) {
this.conversationList.push({
role: 'robot',
answer: data.answer,
type: data.type,
...data.answwerMap,
intentType: data.intentType,
dialogueCount: data.dialogueCount,
askFlag: type === 'add'
})
} else {
if (data.intentType === '1') {
this.conversationList.push({
...data.answwerMap,
role: 'robot',
intentType: data.intentType
})
data.type = '1'
} else if (data.intentType === '2') {
this.conversationList.push({
role: 'robot',
intentType: data.intentType,
text: data.answwerMap.answerText
})
data.type = '1'
} else if (data.intentType === '3') {
this.conversationList.push({
role: 'robot',
intentType: data.intentType,
text: data.answwerMap.guideDesc
})
data.type = '1'
//
} else if (data.intentType === '0') {
} else if (data.intentType === '0' && data.answwerMap.indexName) {
this.conversationList.push({
role: 'robot',
intentType: data.intentType,
...data.answwerMap
})
data.type = '1'
}
// dify
if (data.type === '0') {
@ -397,12 +508,15 @@ export default {
role: 'robot',
answer: data.answer,
type: data.type,
segmentVOList: data.segmentVOList
segmentList: data.segmentList,
...data.answwerMap
})
}
this.$nextTick(() => {
}
setTimeout(() => {
this.loading = false
this.scrollToBottom()
})
}, 2000)
},
//
getIndexType(val) {
@ -421,12 +535,30 @@ export default {
}
},
scrollToBottom() {
const scrollbar = this.$refs.scrollbar
if (scrollbar) {
scrollbar.wrap.scrollTo(0, scrollbar.wrap.scrollHeight)
// const scrollbar = this.$refs.scrollbar
// if (scrollbar) {
// scrollbar.wrap.scrollTo(0, scrollbar.wrap.scrollHeight)
// }
this.$nextTick(() => {
const div = this.$refs.scrollbar
div.scrollTop = div.scrollHeight
})
},
//
handleScroll(event) {
const scrollTop = event.target.scrollTop //
const clientHeight = event.target.clientHeight //
const scrollHeight = this.$refs.scrollbar.scrollHeight //
//
this.distanceToBottom = scrollHeight - (scrollTop + clientHeight)
if (this.distanceToBottom > 2) {
this.isShowDownIcon = true
} else {
this.isShowDownIcon = false
}
},
handleSend() {
if (this.loading) return
if (!this.caseId) {
this.$baseMessage.error('请选择案件!')
return
@ -435,7 +567,7 @@ export default {
this.$baseMessage.error('请输入内容!')
return
}
this.sendText = ''
this.conversationList.push({
role: 'user',
text: this.sendText
@ -445,9 +577,11 @@ export default {
caseId: this.caseId,
query: this.sendText,
conversationId: this.conversationId,
dialogueCount: this.conversationList.length > 2 ? this.conversationList[this.conversationList.length - 2].dialogueCount : '',
type: '0',
intentType: ''
intentType: this.conversationList.length > 2 ? this.conversationList[this.conversationList.length - 2].intentType : ''
})
this.sendText = ''
}
}
}
@ -457,13 +591,14 @@ export default {
background: #FFFFFF;
height: 100%;
position: relative;
padding-top: 24px;
// padding-top: 24px;
display: flex;
.PoliceAi-main {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding-top: 24px;
.case-title {
width: 632px;
height: 98px;
@ -486,6 +621,7 @@ export default {
font-size: 16px;
color: #333333;
margin-right: 16px;
}
::v-deep {
.el-input__inner {
@ -512,8 +648,9 @@ export default {
overflow-y: auto;
width: 1154px;
position: relative;
// padding-right: 16px;
.robot {
.robot-top {
display: flex;
align-items: center;
@ -528,6 +665,21 @@ export default {
color: #3763FF;
}
}
.loading {
display: flex;
background: #F5F7FF;
border-radius: 16px 0px 16px 16px;
line-height: 28px;font-size: 16px;
color: #333333;
padding: 16px;
margin-bottom: 16px;
align-items: center;
img {
width: 38px;
height: 38px;
margin-right: 8px;
}
}
.robot-item {
background: #F5F7FF;
@ -535,9 +687,27 @@ export default {
line-height: 28px;font-size: 16px;
color: #333333;
padding: 16px;
// width: 90%;
margin-bottom: 16px;
display: flex;
flex-direction: column;
.btns {
display: flex;
margin-top: 16px;
.btn-item {
width: 80px;
height: 40px;
box-shadow: 0px 2px 0px 0px rgba(0,0,0,0.04);
border-radius: 6px 6px 6px 6px;
border: 1px solid #3763FF;
margin-right: 24px;
font-size: 16px;
color: #3763FF;
cursor: pointer;
text-align: center;
line-height: 40px;
}
}
.success {
color: #00975E;
font-weight: bold;
@ -573,6 +743,10 @@ export default {
.value {
font-size: 16px;
color: #333333;
width: 900px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
@ -592,6 +766,7 @@ export default {
padding: 16px;
background: #F6F7F9;
border-radius: 6px 6px 6px 6px;
// width: 90%;
.title {
font-size: 16px;
color: #333333;
@ -621,11 +796,43 @@ export default {
}
}
}
.option-list {
display: flex;
flex-direction: column;
.option-item {
display: flex;
align-items: center;
position: relative;
font-size: 16px;
cursor: pointer;
color: #464546;
margin-bottom: 16px;
.name {
border-radius: 9px 9px 9px 9px;
border: 1px solid #D9D9D9;
padding: 8px 36px 8px 16px;
}
i {
margin-left: -32px;
}
}
.option-item:hover {
color: #3763FF;
.name{
border: 1px solid #3763FF;
}
}
}
}
.user-message {
margin: 24px 0;
text-align: right;font-size: 16px;
color: #333333;
padding-right: 16px;
}
.nav-list {
display: flex;
@ -677,7 +884,7 @@ export default {
font-size: 16px;
}
}
img {
.input-img {
width: 60px;
height: 60px;
position: absolute;
@ -727,13 +934,30 @@ export default {
padding-left: 24px;
height: 260px;
.index-list-item {
padding-left: 8px;
font-weight: 400;
font-size: 16px;
color: #333333;
cursor: pointer;
margin-bottom: 24px;
line-height: 45px;
}
.index-list-item:hover {
background: #F2F6FD;
}
}
}
}
.scroll-icon {
position: absolute;
bottom: 77px;
left: 50%;
display: flex;
justify-content: center;
align-items: center;
img {
width: 68px;
height: 68px;
cursor: pointer;
}
}
}

@ -55,8 +55,8 @@ import { ocrAndExtractList } from '@/api/caseDetails/evidence'
import mixin from '@/views/mixin'
export default {
name: 'EvidenceExtract',
mixins: [mixin],
components: { vuedraggable },
mixins: [mixin],
data() {
return {
detailImg: require('@/assets/record/view_detail.png'),
@ -99,13 +99,14 @@ export default {
return [`${baseURL}${commonDownloadFile}${row.fileId}`]
},
getDataList() {
if (!this.$route.query.recordId) return
ocrAndExtractList({
batchNo: this.$route.query.recordId,
caseId: this.$route.params.id
}).then(res => {
if (res.code === 200) {
this.$set(this.gridOptions, 'data', res.data)
this.gridOptions.data = res.data
// this.gridOptions.data = res.data
for (const item of res.data) {
if (item.status !== '2' && item.status !== '3') {
setTimeout(() => {

@ -48,7 +48,7 @@ import UploadRecord from './components/UploadRecord.vue'
import RecordAnalysis from './components/RecordAnalysis.vue'
import { getRocordInfo, queryFileList } from '@/api/caseDetails/ocr'
export default {
name: 'OcrRecord',
name: 'AddRecord',
components: { RecordIdentify, RecordProofread, UploadRecord, RecordAnalysis },
data() {
return {
@ -75,6 +75,7 @@ export default {
},
mounted() {
this.$store.dispatch('record/setRecordInfo', {})
// const pathList = this.$route.path.split('/')
if (this.$route.query.imgRecordStatus === '1') {
this.activeStep = 1
} else if (this.$route.query.imgRecordStatus === '2') {

@ -237,7 +237,7 @@ export default {
}
}
.right {
flex: 1;
width: calc(100vw - 700px);
display: flex;
flex-direction: column;
background: radial-gradient(circle, rgba(255, 255, 255, 0.05), rgba(66, 135, 255, 0.05));

@ -38,9 +38,10 @@
<el-input v-model="searchName" class="search" placeholder="搜索名称" style="width: 300px" />
</div>
<vxe-grid
v-if="gridOptions.data.length > 0"
ref="entityTable"
v-bind="gridOptions"
style="margin-top: 10px;width: calc(100vw - 618px);"
style="margin-top: 10px"
>
<template #status="{row}">
<div v-if="row.processStatus === '2'" class="status">

@ -22,7 +22,7 @@
<el-input v-model="searchName" placeholder="搜索名称" style="width: 300px" />
</div>
<vxe-grid v-bind="gridOptions" style="margin-top: 10px">
<vxe-grid v-if="gridOptions.data.length > 0" v-bind="gridOptions" style="margin-top: 10px">
<template #opera="{row}">
<!-- <el-button v-if="row.children.length === 0" type="text" icon="el-icon-video-play" :disabled="!isEdit" title="笔录分析" @click="handleCreateAtlas(row)" /> -->
@ -120,7 +120,7 @@ export default {
{ title: '最新时间', field: 'updateTime' },
{ title: '操作', slots: { default: 'opera' }, fixed: 'right', width: '200px' }
],
data: [{ name: '裴金禄', '笔录序号': '1', roleName: '被害人', confessionMaterial: '3', questioner: '1', startTime: '2024/6/26', newDate: '2024/6/26', endTime: '2024/6/26' }]
data: []
}
}
},

@ -20,7 +20,7 @@
<el-option v-for="item in indexSourceList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input v-model="atomicName" placeholder="原子指标名称" clearable style="width: 200px;margin-left: 16px;" />
<vxe-grid v-bind="gridOptions" style="margin-top: 10px">
<vxe-grid v-if="gridOptions.data.length > 0" v-bind="gridOptions" style="margin-top: 10px">
<template #operate="{row}">
<div class="btn-item">
<span>{{ row.record }}</span>
@ -120,7 +120,7 @@ export default {
isExpand: {
handler: function(newVal, oldVal) {
if (newVal !== oldVal) {
this.tableHeight(this.isExpand ? 570 : 360)
this.tableHeight(this.isExpand ? 590 : 370)
}
},
immediate: true

@ -20,7 +20,7 @@
<el-option v-for="item in indexSourceList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input v-model="atomicName" placeholder="原子指标名称" clearable style="width: 200px;margin-left: 16px;" />
<vxe-grid v-bind="gridOptions" style="margin-top: 10px">
<vxe-grid v-bind="gridOptions" v-if="gridOptions.data.length > 0" style="margin-top: 10px">
<template #operate="{row}">
<div class="btn-item">
<span>{{ row.record }}</span>
@ -123,7 +123,7 @@ export default {
isExpand: {
handler: function(newVal, oldVal) {
if (newVal !== oldVal) {
this.tableHeight(this.isExpand ? 570 : 360)
this.tableHeight(this.isExpand ? 590 : 370)
}
},
immediate: true

@ -20,7 +20,7 @@
<el-option v-for="item in indexSourceList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input v-model="atomicName" placeholder="原子指标名称" clearable style="width: 200px;margin-left: 16px;" />
<vxe-grid v-bind="gridOptions" style="margin-top: 10px">
<vxe-grid v-if="gridOptions.data.length > 0" v-bind="gridOptions" style="margin-top: 10px">
<template #operate="{row}">
<div class="btn-item">
<span>{{ row.record }}</span>
@ -28,7 +28,7 @@
</div>
</template>
<template #detail="{row}">
<span v-if="row.parentIndexName"><a v-if="!row.isRead" style="text-decoration: underline;" @click="handleDetails(row)">{{ row.indexName }}</a><span style="text-decoration: underline;cursor: pointer;" v-else @click="handleDetails(row)">{{ row.indexName }}</span></span>
<span v-if="row.parentIndexName"><a v-if="!row.isRead" style="text-decoration: underline;" @click="handleDetails(row)">{{ row.indexName }}</a><span v-else style="text-decoration: underline;cursor: pointer;" @click="handleDetails(row)">{{ row.indexName }}</span></span>
<span v-else>{{ row.indexName }}</span>
</template>
<template #result="{row}">
@ -95,8 +95,8 @@ export default {
{ title: '序号', type: 'seq', width: '80px' },
{ title: '分析结果', width: '200px', field: 'indexResult', slots: { default: 'result' }},
// { title: '', width: '200px', slots: { default: 'operate' }, align: 'center' },
{ title: '指标名称', field: 'indexName',slots: { default: 'detail' }, align: 'left' },
{ title: '分值', width: '200px', field: 'score' },
{ title: '指标名称', field: 'indexName', slots: { default: 'detail' }, align: 'left' },
{ title: '分值', width: '200px', field: 'score' }
// { title: '', width: '200px', field: 'indexSource', formatter: ({ cellValue }) => {
// return cellValue ? this.indexSourceList.find(item => item.value === cellValue).label : ''
// } }
@ -120,7 +120,7 @@ export default {
isExpand: {
handler: function(newVal, oldVal) {
if (newVal !== oldVal) {
this.tableHeight(this.isExpand ? 570 : 360)
this.tableHeight(this.isExpand ? 580 : 370)
}
},
immediate: true

@ -185,7 +185,7 @@ export default {
for (const item of this.fileList) {
if (item.name === file.name) {
if (!item.fileId) return
this.downloadFile(`${baseURL}${commonDownloadFile}${item.fileId}`, item.name)
this.downloadFile(`${baseURL}${commonDownloadFile}${item.fileId}&printWaterMarket=true&download=true`, item.name)
}
}
},

@ -253,7 +253,7 @@ export default {
for (const item of this.fileList) {
if (item.name === file.name) {
if (!item.id) return
this.downloadFile(`${baseURL}${commonDownloadFile}${item.id}`, item.name)
this.downloadFile(`${baseURL}${commonDownloadFile}${item.id}&printWaterMarket=true&download=true`, item.name)
}
}
},

@ -106,7 +106,7 @@
</div>
</div>
</div>
<div class="flex-row details-info" :style="{ height: expand ? 'calc(100% - 270px)' : 'calc(100% - 80px)' }">
<div class="flex-row details-info" :style="{ height: expand ? 'calc(100% - 300px)' : 'calc(100% - 85px)' }">
<div class="info-left">
<el-tree
v-if="currentKey"
@ -218,7 +218,6 @@ export default {
//
this.isEdit = this.$route.query.isEdit === '1'
this.fetchData()
},
methods: {
// node
@ -332,6 +331,7 @@ export default {
},
//
handleAnalysis() {
if (!this.showFlag) return
this.showFlag = false
this.handleConfirmAnalysis()
let value = 80
@ -399,6 +399,7 @@ export default {
height: 100%;
color: #333333;
box-sizing: border-box;
min-width: 1800px;
.btn-icon {
padding: 8px 20px;
@ -627,7 +628,7 @@ export default {
}
.info-left {
min-width: 245px;
// overflow-y: auto;
overflow-y: auto;
// overflow-x: hidden;
}
.info-right {

@ -209,7 +209,7 @@ export default {
padding: 20px;
box-sizing: border-box;
margin-top: 10px;
height: calc(100% - 120px);
height: calc(100% - 123px);
}
.expand-details {
background: #F6F6F6;

@ -53,7 +53,7 @@
<span class="main-title">{{ item.caseName }}</span>
</div>
<div>
<img src="~@/assets/caseManagement/duihua@2x.png" class="tag-icon" @click.stop="handleContact(item)">
<!-- <img src="~@/assets/caseManagement/duihua@2x.png" class="tag-icon" @click.stop="handleContact(item)"> -->
<!-- <img src="~@/assets/caseManagement/tuola@2x.png" class="tag-icon mover"> -->
</div>
</div>

@ -128,7 +128,7 @@ export default {
padding: 20px;
box-sizing: border-box;
margin-top: 10px;
height: calc(100% - 120px);
height: calc(100% - 123px);
}
.expand-details {
background: #F6F6F6;

@ -176,7 +176,7 @@ export default {
prompt: [{ required: true, message: 'prompt内容不能为空!', trigger: 'blur' }],
queryLang: [{ required: true, message: '查询语句不能为空!', trigger: 'blur' }],
name: [{ required: true, message: '原子指标名称不能为空!', trigger: 'blur' }],
categoryIdPath: [{ required: true, message: '分类不能为空!', trigger: 'change' }],
categoryIdPath: [{ required: true, message: '分类不能为空!', trigger: 'blur' }],
promptId: [{ required: true, message: '查询语句不能为空!', trigger: 'change' }]
},
treeData: [],
@ -207,6 +207,7 @@ export default {
this.selectInfo.extractAttributes = data.properties ? data.properties.split(',') : []
this.selectInfo.promptName = data.promptName
this.selectInfo.promptId = data.promptId
this.$refs.form.clearValidate()
})
},
//
@ -223,7 +224,7 @@ export default {
} else {
this.ruleForm = { indexSource: '2' }
}
this.$refs.form.clearValidate()
// this.$refs.form.clearValidate()
},
//
@ -274,6 +275,7 @@ export default {
//
changeType(val) {
this.ruleForm = { indexSource: val, caseType: this.ruleForm.caseType, name: this.ruleForm.name }
this.$refs.form.clearValidate()
// this.ruleForm['indexSource'] = val
}
}

@ -138,7 +138,7 @@ export default {
padding: 20px;
box-sizing: border-box;
margin-top: 10px;
height: calc(100% - 120px);
height: calc(100% - 123px);
}
.expand-details {
background: #F6F6F6;

@ -378,6 +378,10 @@ export default {
if (val === '3' && subItem.indexSource === '3') {
this.$set(subItem, 'operator', '>')
}
if (val === '4' && subItem.indexSource === '3') {
this.$set(subItem, 'operator', '')
this.$set(subItem, 'value', '')
}
},
//
selectPropertyKey(val, items, id) {

@ -163,7 +163,7 @@ export default {
padding: 20px;
box-sizing: border-box;
margin-top: 10px;
height: calc(100% - 120px);
height: calc(100% - 123px);
}
.expand-details {
background: #F6F6F6;

@ -62,6 +62,7 @@ module.exports = {
target: baseURL,
/* 允许跨域将请求地址host修改为和被请求的接口一致 */
changeOrigin: true,
withCredentials: true,
/* 路径重写 */
pathRewrite: {
'^/fuHsiApi': ''

Loading…
Cancel
Save