Files
sgxt_web/src/views/backOfficeSystem/ResearchJudgment/MoralAnalysis/index.vue
2025-08-27 17:26:29 +08:00

371 lines
13 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<div class="titleBox">
<PageTitle title="情报语义分析"></PageTitle>
</div>
<div class="flex just-between">
<!-- 左边 -->
<div class="ww49" style="min-width: 647px;">
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch">
<el-button type="primary" @click="addForm('add',null)">新增</el-button>
</Search>
</div>
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight1"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
>
<template #controls="{ row }">
<el-link type="primary" @click="addForm('edit', row.id)">编辑</el-link>
<el-link type="danger" @click="delDictItem(row.id)">删除</el-link>
</template>
</MyTable>
<div class="txetBox">
{{ container.text }}
</div>
<div class="footBnt">
<el-button type="primary" @click="showText = true">导入</el-button>
<span class="relative ml10">
<el-button type="primary" v-loading="btnLoading" @click="handleFx">语义分析</el-button>
<span v-if="btnLoading" class="f12 absolute nowrap" style="color: #333333; left: 92px;bottom: 5px;">数据解析中......</span>
</span>
</div>
</div>
</div>
<!-- 右边表格 -->
<div class="ww49">
<div ref="searchBox">
<Search :searchArr="searchConfigerR" @submit="onSearchR" />
</div>
<div class="tabBox">
<MyTable
:tableData="pageData.tableDataR"
:tableColumn="pageData.tableColumnR"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
element-loading-text="模型加载中......"
:tableConfiger="pageData.tableConfigerR"
:controlsWidth="pageData.controlsWidthR"
>
<template #xlLx="{row}">
<DictTag :tag="false" :value="row.xlLx" :options="D_GS_XS_LX" />
</template>
<template #controls="{ row }">
<el-link type="primary" @click="lookdetail('edit', row)">编辑</el-link>
<el-link type="primary" @click="lookdetail('detail', row)">详情</el-link>
<el-link type="danger" @click="delDictItemRight(row.id)">删除</el-link>
</template>
</MyTable>
<Pages
@changeNo="changeNo"
@changeSize="changeSize"
:tableHeight="pageData.tableHeight"
:pageConfiger="{ ...pageData.pageConfigerR }"
/>
</div>
</div>
</div>
<!-- 编辑详情 -->
<EditAddForm ref="detailDiloag" @updateDate="getList" />
<Detail ref="detailForm" @change="getjxListR" v-if="isShow" :dic="{D_BZ_SF,D_BZ_XB,D_GS_XS_LY,D_BZ_SSZT,D_GS_XS_LX ,D_GS_XS_QTLX}" />
<!-- 文字解析 -->
<ExtractionText v-model="showText" @change="getText"></ExtractionText>
</div>
</template>
<script setup>
import ExtractionText from "@/components/ExtractionText/index.vue";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import EditAddForm from "./components/editAddForm.vue";
import Detail from "./components/detail.vue";
import { qcckGet, qcckPost, ParsingText } from "@/api/qcckApi.js";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const {D_GS_ZDQT_FXDJ,D_GS_XS_ZLLX,D_GS_XS_CZZT,D_GS_XS_LY, D_BZ_SSZT,D_BZ_SF,D_GS_XS_LX ,D_GS_XS_QTLX,D_BZ_XB,D_BZ_XSSHZT} = proxy.$dict("D_GS_ZDQT_FXDJ","D_GS_XS_ZLLX","D_GS_XS_CZZT","D_GS_XS_LY","D_BZ_SSZT","D_BZ_SF","D_GS_XS_LX","D_GS_XS_QTLX","D_BZ_XB","D_BZ_XSSHZT"); //获取字典数据
const detailDiloag = ref();
const detailForm = ref();
const searchBox = ref(); //搜索框
const showText = ref(false);
const isShow = ref(false);
const searchConfiger = ref([
{
label: "语义名称",
prop: "yymc",
placeholder: "请输入语义名称",
showType: "input"
},
{
label: "要素类型",
prop: "yslx",
placeholder: "请输入要素类型",
showType: "input"
},
{
label: "要素名称",
prop: "ysmc",
placeholder: "请输入要素名称",
showType: "input"
}
]);
const searchConfigerR = ref([
{
label: "线索名称",
prop: "xsMc",
placeholder: "请输入线索名称",
showType: "input"
},
{
label: "线索类型",
prop: "xlLx",
placeholder: "请选择线索类型",
showType: "select",
options:D_GS_XS_LX
},
{
label: "内容关键字",
prop: "xsNr",
placeholder: "请输入内容关键字",
showType: "input"
}
]);
const queryFrom = ref({});
const queryFromR = ref({});
const container = ref({})
const btnLoading = ref(false)
const prsentText = ref(null)
const pageData = reactive({
tableData: [], //表格数据
tableDataR: [], //表格数据
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
tableHeight1:300,
tableConfigerR: {
rowHieght: 61,
showSelectType: null,
loading: false
},
pageConfigerR: {
total: 0,
pageSize: 20,
pageCurrent: 1
}, //分页
controlsWidth: 120, //操作栏宽度
controlsWidthR: 140, //操作栏宽度
tableColumn: [
{ label: "语义名称", prop: "yymc",showOverflowTooltip:true },
{ label: "要素类型", prop: "yslx",showOverflowTooltip:true },
{ label: "要素名称", prop: "ysmc",showOverflowTooltip:true },
{ label: "要素描述", prop: "ysms",showOverflowTooltip:true },
],
tableColumnR: [
{ label: "线索名称", prop: "xsMc",showOverflowTooltip:true },
{ label: "线索类型", prop: "xlLx",showOverflowTooltip:true,showSolt:true },
{ label: "指向地点", prop: "zxdz",showOverflowTooltip:true },
{ label: "线索内容", prop: "xsNr",showOverflowTooltip:true },
],
});
onMounted(() => {
tabHeightFn();
getList();
getjxListR();
});
// 搜索
const onSearch = (val) => {
queryFrom.value = { ...val };
getList();
};
const getList = () => {
pageData.tableConfiger.loading = true;
qcckGet(queryFrom.value,'/mosty-gsxt/qbyy/selectList').then((res)=>{
pageData.tableData = res || [];
pageData.tableConfiger.loading = false;
})
};
// 搜索
const onSearchR = (val) => {
queryFromR.value = { ...val };
pageData.tableConfigerR.pageCurrent = 1;
getjxListR();
};
// 获取数据
const getjxListR = () => {
pageData.tableConfigerR.loading = true;
let params = { ...queryFromR.value, cjLx:2, }
qcckGet(params,'/mosty-gsxt/qbcj/selectPage').then((res)=>{
pageData.tableDataR = res.records || [];
pageData.pageConfigerR.total = res.total;
pageData.tableConfigerR.loading = false;
}).catch(()=>{
pageData.tableConfigerR.loading = false;
})
};
// 删除
const delDictItem = (id) => {
proxy.$confirm("确定要删除", "警告", {type: "warning"}).then(() => {
qcckPost({id},'/mosty-gsxt/qbyy/delete').then(()=>{
proxy.$message({ type: "success", message: "删除成功" });
getList();
})
}).catch(() => {});
};
// 删除右边
const delDictItemRight = (id) => {
proxy.$confirm("确定要删除", "警告", {type: "warning"}).then(() => {
qcckPost({id},'/mosty-gsxt/qbcj/delete').then(()=>{
proxy.$message({ type: "success", message: "删除成功" });
getjxListR();
})
}).catch(() => {});
};
// 新增数据 -- 左边
const addForm = (type, id) =>{
detailDiloag.value.init(type, id);
}
// 新增数据 -- 左边
const lookdetail = (type, row) =>{
isShow.value = true;
setTimeout(()=>{
detailForm.value.init(type, row);
},500)
}
const changeNo = (val) => {
pageData.pageConfigerR.pageCurrent = val;
getListR();
};
const changeSize = (val) => {
pageData.pageConfigerR.pageSize = val;
getListR();
};
// 提取数据
const getText = (val) =>{
prsentText.value = null; //先清空
container.value = val;
let obj = {
"model": "deepseek-reasoner",
"messages": [
{
"role": "system",
"content":  "# 角色定位\n你是一名资深警务人员尤其擅长对警情、案件、线索等非结构化文本数据进行阅读理解并从中提取各种对象特征信息进行结构化并总结各种对象之间的关联关系。\n##  - person:人物   - id:唯一值   - name:姓名   - enName:英文姓名   - nickName:绰号   - aliasName:别名   - screenName:网名   - idcard:身份证号码   - phoneNo:手机号码   - bankCard:银行卡号   - passporNumber:护照号码   - permanentResidenceAddress:户籍地址   - residenceAddress:现住地址- jbxx:基本信息- id:唯一值     - xsmc:线索名称     - xslx:线索类型     - qbly:情报来源     - kssj:开始时间     - jssj:结束时间     - qtlx:群体类型     - qtmc:群体名称     - sjrs:设计人数     - sbdw:送报单- yjtq:语义提取     "
},
{
"role": "user",
"content": "# 任务\n根据警情信息识别对象信息以及对象之间的关联关系。最后以json形式输出不要做任何解释。直接给出完整的json\n## 注意\n- 各种不同类型的对象分别用对象数组存储;\n- 对象之间的关系存储在relation数组中\n\n# 警情信息\n  - "
}
],
"max_tokens": 4096,
"stream": false
}
let marks = (pageData.tableData.splice(0,10).map(v=> '- '+v.yymc)).join('     ');
obj.messages[0].content = obj.messages[0].content + marks + "## 注意点\n- 地址信息能够根据上下文信息按照省、市、县、街道/乡镇、路名分段补全并标准化。例如:四川省 成都市 高新区 桂溪街道 交子大道11号\n- 对象之间的关联关系由对象类型、对象id、关系类型、目标对象类型、目标对象id 5个属性组成。\n"
// 拼接字典 线索类型:
let xslx = '线索类型是一个字典,字典内容包括:' + (D_GS_XS_LX.value.map(item=>item.dm+':'+item.zdmc).join(','))+'\n'
let qbLy = '情报来源是一个字典,字典内容包括:' + (D_GS_XS_LY.value.map(item=>item.dm+':'+item.zdmc).join(','))+'\n'
let sszt = '所属专题是一个字典,字典内容包括:' + (D_BZ_SSZT.value.map(item=>item.dm+':'+item.zdmc).join(','))+'\n'
let time = '时间必须按照 YYYY-MM-DD HH:mm:ss 的格式 \n'
obj.messages[0].content = obj.messages[0].content + xslx + qbLy + sszt + time;
obj.messages[1].content = obj.messages[1].content + val.text
prsentText.value = obj;
}
const handleFx = () => {
if(!prsentText.value) return proxy.$message({ type: "warning", message: "请先上传要解析的文件" });;
btnLoading.value = true;
pageData.tableConfigerR.loading = true;
ParsingText( prsentText.value,(res)=>{
pageData.tableConfigerR.loading = false;
btnLoading.value = false;
let content = res.data.choices[0].message.content;
let message = null;
try{
message = content ? JSON.parse(content):''
}catch(err){
proxy.$message({ type: "danger", message: "解析异常,请重新上传解析" });
}
if(!message) return proxy.$message({ type: "danger", message: "解析异常,请重新上传解析" });
let marks = '';
let arr = message.yjtq || []
arr.forEach(item=>{
for(let key in item){
marks = marks+ key+':'+ item[key]+' , '
}
})
let params = {
...message.jbxx[0],
ryList:message.ryList,
cjLx:2,
xsNr:container.value.text+' , ' + marks,
fjdz:container.value.fjdz
}
qcckPost(params,'/mosty-gsxt/qbcj/add').then((res)=>{
container.value = {};
getjxListR()
})
})
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 280;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style lang="scss" scoped>
.footBnt{
width: 100%;
position: absolute;
bottom: 10px;
display: flex;
justify-content: center;
}
.txetBox{
position: absolute;
bottom: 50px;
height: 210px;
width: calc(100% - 20px);
padding: 0 10px;
box-sizing: border-box;
border: 2px dashed #ccc;
margin: 0 10px;
color: #333;
}
</style>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>