feat:赋分模型页面开发

dev_2.3
xiangcongshuai 2 weeks ago
parent af5dccf1f1
commit f3eb76ac94

@ -38,3 +38,52 @@ export function listAtomicIndexAttributeScope(data) {
data
})
}
/** 查看赋分模型列表 */
export function queryModelList(data) {
return request({
url: `/scoringModel/pageList`,
method: 'get',
params: data
})
}
/** 保存赋分模型 */
export function saveScoringModel(data) {
return request({
url: `/scoringModel/save`,
method: 'post',
data
})
}
/** 修改赋分模型 */
export function updateScoringModel(data) {
return request({
url: `/scoringModel/update`,
method: 'post',
data
})
}
/** 复制赋分模型 */
export function copyScoringModel(data) {
return request({
url: `/scoringModel/copy`,
method: 'post',
data
})
}
/** 删除赋分模型 */
export function deleteScoringModel(data) {
return request({
url: `/scoringModel/delete`,
method: 'post',
data
})
}
/** 查询原子指标被使用情况 */
export function queryAtomicUsed(data) {
return request({
url: `/modelIndex/atomic/used`,
method: 'get',
params: data
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

@ -35,8 +35,9 @@
class="drawer-footer"
>
<slot name="footer">
<el-button type="primary" plain @click="reset" style="width: 150px"> </el-button>
<el-button type="primary" @click="submit" style="width: 150px"> </el-button>
<el-button v-if="!drawerOption.isClosed" type="primary" plain style="width: 150px" @click="reset"> </el-button>
<el-button v-if="drawerOption.isClosed" style="width: 150px" @click="closed"></el-button>
<el-button type="primary" style="width: 150px" @click="submit"> </el-button>
</slot>
</div>
<div
@ -77,6 +78,9 @@ export default {
reset() {
this.$emit('onReset')
},
closed() {
this.drawerOption.show = false
},
//
submit() {
this.$emit('onSubmit', status => {

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

@ -117,6 +117,13 @@ export const asyncRoutes = [
component: () => import('@/views/ruleEngine/atomicIndex/index.vue'),
meta: { title: '原子指标', affix: false, subtitle: '提取案件信息的指标项无法在拆分的指标' }
},
{
path: '/scoring-model',
name: 'ScoringModel',
permission: 'p_atomicRule',
component: () => import('@/views/ruleEngine/scoringModel/index.vue'),
meta: { title: '赋分模型', affix: false, subtitle: '大模型分析提取案件信息的指标项' }
},
{
path: '/index-rule',
name: 'IndexRule',

@ -55,9 +55,9 @@
<el-descriptions :column="4">
<el-descriptions-item label="案件编号">{{ caseData['caseNo'] }}</el-descriptions-item>
<el-descriptions-item label="案件名称">{{ caseData['caseName'] }}</el-descriptions-item>
<el-descriptions-item label="案件类型" span="2">{{ caseData.caseTypeName }}</el-descriptions-item>
<!-- <el-descriptions-item label="案件类型" span="2">{{ caseData.caseTypeName }}</el-descriptions-item> -->
<el-descriptions-item label="案件状态">{{ caseData.caseStatusName }}</el-descriptions-item>
<el-descriptions-item label="到案方式">{{ caseData.crimeModeName }}</el-descriptions-item>
<!-- <el-descriptions-item label="到案方式">{{ caseData.crimeModeName }}</el-descriptions-item> -->
<!-- <el-descriptions-item label="立案时间">{{ caseData.registerTime || '暂未添加,上传笔录后自动生成' }}</el-descriptions-item>
<el-descriptions-item label="受理时间">{{ caseData.acceptTime || '暂未添加,上传笔录后自动生成' }}</el-descriptions-item> -->

@ -18,7 +18,7 @@
</el-form-item>
<el-form-item label="案件类型" prop="caseType">
<el-select v-model="caseForm['caseType']" clearable placeholder="请选择案件类型">
<el-option v-for="item in caseTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in caseTypeOptions" :key="item.id" :label="item.modelName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="案件状态" prop="caseStatus">
@ -26,11 +26,11 @@
<el-option v-for="item in caseStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="到案方式" prop="crimeMode">
<!-- <el-form-item label="到案方式" prop="crimeMode">
<el-select v-model="caseForm['crimeMode']" clearable placeholder="请选择到案方式">
<el-option v-for="item in crimeModeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form-item> -->
<el-form-item label="案件概述" prop="caseDetail">
<el-input v-model="caseForm['caseDetail']" type="textarea" :rows="5" placeholder="请输入案件概述" />
</el-form-item>
@ -49,6 +49,7 @@
import { addCaseInfo, checkCaseNo } from '@/api/caseManagement'
import { validIdCard } from '@/utils/validate'
import { debounce } from '@/utils'
import { queryModelList} from '@/api/indexRule/index'
export default {
name: 'EditCaseInfo',
data() {
@ -73,7 +74,7 @@ export default {
show: false
},
//
caseTypeOptions: JSON.parse(sessionStorage.getItem('case_type')),
caseTypeOptions: [],
//
caseStatusOptions: JSON.parse(sessionStorage.getItem('case_status')),
//
@ -111,12 +112,20 @@ export default {
this.isEdit = isEdit
this.drawerOption.show = true
this.drawerOption.title = isEdit ? '编辑案件' : '新建案件'
this.getModelList()
this.$nextTick(() => {
const _this = this
const formData = data ? JSON.parse(JSON.stringify(data)) : { }
_this.caseForm = data ? formData : (isEdit ? formData : { })
})
},
getModelList() {
queryModelList({}, 1, 9999).then(res => {
if (res.code === 200) {
this.caseTypeOptions = res.data.records
}
})
},
//
handleReset() {
if (this.isEdit) {

@ -7,11 +7,11 @@
<el-form ref="form" :model="dataInfo" :rules="rules" label-width="120px">
<el-form-item label="案件类型" prop="caseType">
<el-select v-model="dataInfo['caseType']" style="width: 100%;" clearable placeholder="请选择案件类型">
<el-option v-for="item in caseTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in caseTypeOptions" :key="item.id" :label="item.modelName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="提示词类型" prop="type">
<el-select disabled v-model="dataInfo['type']" style="width: 100%;" placeholder="请选择提示词类型" @change="selectType">
<el-select v-model="dataInfo['type']" disabled style="width: 100%;" placeholder="请选择提示词类型" @change="selectType">
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
@ -128,6 +128,7 @@ import PromptInput from './PromptInput.vue'
import { addOrUpdPrompt, getChunkClassify, queryPromptDetails } from '@/api/promptManagement'
import * as vuedraggable from 'vuedraggable'
import mixin from '@/views/mixin'
import { queryModelList } from '@/api/indexRule/index'
export default {
name: 'AddPrompt',
components: {
@ -199,7 +200,7 @@ export default {
extractList: JSON.parse(sessionStorage.getItem('prompt_attribute_valuetype')),
typeData: [], //
//
caseTypeOptions: JSON.parse(sessionStorage.getItem('case_type')),
caseTypeOptions: [],
typeOptions: JSON.parse(sessionStorage.getItem('prompt_type')),
//
promptTextList: JSON.parse(sessionStorage.getItem('prompt_prototype_default_text'))
@ -209,7 +210,7 @@ export default {
mounted() {
this.getTreeList()
this.queryChunkClassify()
this.getModelList()
if (this.$route.params.id) {
this.getDetails()
} else {
@ -223,6 +224,13 @@ export default {
this.typeData = res.data
})
},
getModelList() {
queryModelList({}, 1, 9999).then(res => {
if (res.code === 200) {
this.caseTypeOptions = res.data.records
}
})
},
//
getDetails() {
this.showFlag = false
@ -390,7 +398,7 @@ export default {
display: flex;
flex-direction: column;
padding: 0 40px;
.tip {
width: 100%;
height: 70px;

@ -19,9 +19,9 @@
<el-select v-model="ruleForm.caseType" :disabled="isView" placeholder="请选择案件类型" style="width: 100%">
<el-option
v-for="item in caseTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
:key="item.id"
:label="item.modelName"
:value="item.id"
/>
</el-select>
</el-form-item>
@ -125,6 +125,7 @@ import { addOrUpdAtomicIndex } from '@/api/atomicIndex'
import SelectSql from './SelectSql.vue'
import { getCaseEvidenceTree } from '@/api/caseDetails/evidence'
import GraphDebug from './GraphDebug.vue'
import { queryModelList} from '@/api/indexRule/index'
export default {
name: 'EditAtomic',
components: {
@ -145,7 +146,7 @@ export default {
}, //
//
caseTypeOptions: JSON.parse(sessionStorage.getItem('case_type')),
caseTypeOptions: [],
// prompt
promptTagOptions: [],
//
@ -197,6 +198,7 @@ export default {
promptId: '',
extractAttributes: []
}
this.getModelList()
this.getTreeList()
this.$nextTick(() => {
const _this = this
@ -210,6 +212,13 @@ export default {
this.$refs.form.clearValidate()
})
},
getModelList() {
queryModelList({}, 1, 9999).then(res => {
if (res.code === 200) {
this.caseTypeOptions = res.data.records
}
})
},
//
handleReset() {
this.selectInfo = {

@ -15,9 +15,10 @@
</div>
<vxe-grid v-bind="gridOptions" style="margin-top: 20px">
<template #operate="{row}">
<el-button type="text" @click="handleEdit(row)"></el-button>
<el-button type="text" @click="handleView(row)"></el-button>
<el-button type="text" style="color: red" @click="handleDel(row)"></el-button>
<el-button type="text" icon="el-icon-edit" @click="handleEdit(row)" />
<el-button type="text" icon="el-icon-view" title="查看明细" @click="handleView(row)" />
<el-button type="text" style="color: red" icon="el-icon-delete" @click="handleDel(row)" />
</template>
</vxe-grid>
<div style="text-align: center">
@ -29,6 +30,35 @@
/>
</div>
</div>
<el-dialog
:visible.sync="dialogVisible"
width="500px"
append-to-body
:before-close="handleClose"
>
<template>
<div class="del-folder">
<div class="header">
<img src="@/assets/record/error.png" alt="">
<span>确认删除原子指标</span>
</div>
<div v-if="atomicList.length > 0" class="content-text"></div>
<div v-if="atomicList.length === 0" class="content-text">
无关联案件模型确定永久删除?
</div>
<div class="atomic-list">
<span v-for="(item,index) in atomicList" :key="index">
{{ `${item.modelName}${item.atomicIndexName}` }}
</span>
</div>
<div class="footer-btns">
<div class="btn" @click="delItem"></div>
<div class="reset_btn" @click="handleClose"></div>
</div>
</div>
</template>
</el-dialog>
<!--编辑弹窗-->
<edit-atomic ref="edit" @reloadData="fetchData" />
</div>
@ -40,6 +70,7 @@ import IndexAtlas from '@/views/ruleEngine/indexRule/components/IndexAtlas.vue'
import mixin from '@/views/mixin'
import EditAtomic from '@/views/ruleEngine/atomicIndex/components/EditAtomic.vue'
import { queryAtomicIndex, delAtomicIndex } from '@/api/atomicIndex'
import { queryAtomicUsed } from '@/api/indexRule/index'
export default {
name: 'Index',
@ -54,6 +85,9 @@ export default {
{ label: '指标来源', model: 'indexSource', type: 'select', option: JSON.parse(sessionStorage.getItem('index_source')) },
{ label: '最新时间', model: 'updateTime', type: 'datetimerange' }
],
dialogVisible: false,
atomicList: [],
selectAtomic: '',
//
gridOptions: {
...mixin.data().gridOptions,
@ -65,9 +99,9 @@ export default {
return null
},
columns: [
{ title: '序号', type: 'seq', width: '50px' },
{ title: '序号', type: 'seq', width: '50px' },
{ title: '原子指标', field: 'name' },
{ title: '案件类型', field: 'caseTypeName', sortable: true },
// { title: '', field: 'caseTypeName', sortable: true },
{ title: '指标来源', field: 'indexSourceName', sortable: true },
// { title: '', field: 'connectStatus' },
{ title: '最新时间', field: 'updateTime', sortable: true },
@ -94,6 +128,15 @@ export default {
this.queryForm.total = res.data.total
})
},
async delItem() {
const { code, msg } = await delAtomicIndex(this.selectAtomic)
code === 200 ? this.$baseMessage.success(msg || '删除成功!') : this.$baseMessage.error(msg || '删除失败!')
this.fetchData()
this.dialogVisible = false
},
handleClose() {
this.dialogVisible = false
},
//
handleAdd() {
this.$refs.edit.show()
@ -110,13 +153,23 @@ export default {
handleView(row) {
this.$refs.edit.show(row, false)
},
// 使
async getAtomicUsed(val) {
const res = await queryAtomicUsed({ atomicIndexId: val })
if (res.code === 200) {
this.atomicList = res.data
}
},
//
handleDel(row) {
this.$baseConfirm('确定要删除吗?', null, async() => {
const { code, msg } = await delAtomicIndex(row.id)
code === 200 ? this.$baseMessage.success(msg || '删除成功!') : this.$baseMessage.error(msg || '删除失败!')
this.fetchData()
})
this.dialogVisible = true
this.getAtomicUsed(row.id)
this.selectAtomic = row.id
// this.$baseConfirm('?', null, async() => {
// const { code, msg } = await delAtomicIndex(row.id)
// code === 200 ? this.$baseMessage.success(msg || '!') : this.$baseMessage.error(msg || '!')
// this.fetchData()
// })
},
//
onSearch(data, callback) {
@ -159,3 +212,81 @@ export default {
}
}
</style>
<style lang="scss" scoped>
.dialog-content {
border-radius: 5px;
padding: 20px;
box-sizing: border-box;
}
::v-deep .el-dialog__header {
padding: 0;
}
::v-deep .el-dialog__body {
padding: 0 !important;
}
::v-deep .el-dialog {
// background: linear-gradient(to bottom, #E1ECFE, #FFFFFF);
}
.del-folder {
padding: 24px;
.header {
display: flex;
img {
width: 28px;
height: 28px;
margin-right: 16px;
}
font-weight: bold;
font-size: 20px;
color: #333333;
}
.content-text {
margin-top: 12px;
font-weight: 400;
font-size: 16px;
color: #666666;
line-height: 25px;
padding-left: 45px;
}
.atomic-list {
display: flex;
flex-direction: column;
padding-left: 45px;
margin-top: 8px;
span {
font-size: 14px;
color: #666666;
margin-top: 4px;
}
}
.footer-btns {
padding-top: 24px;
display: flex;
flex-direction: row-reverse;
.btn {
padding: 8px 24px;
background: #3763FF;
box-shadow: 0px 2px 0px 0px rgba(0,0,0,0.04);
border-radius: 6px 6px 6px 6px;
text-align: center;
font-size: 16px;
color: #FFFFFF;
cursor: pointer;
margin-left: 16px;
}
.reset_btn {
padding: 8px 24px;
background: #FFFFFF;
box-shadow: 0px 2px 0px 0px rgba(0,0,0,0.04);
border-radius: 6px 6px 6px 6px;
border: 1px solid #3763FF;
text-align: center;
font-size: 16px;
color: #3763FF;
cursor: pointer;
margin-left: 16px;
}
}
}
</style>

@ -46,6 +46,11 @@
style="margin-top: 20px"
>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="赋分模型">
<el-input v-model="modelName" readonly />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="指标名称" prop="name">
<el-input v-model="ruleForm['name']" placeholder="请输入指标名称" />
@ -68,13 +73,13 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<!-- <el-col :span="12">
<el-form-item label="案件类型" prop="caseType">
<el-select v-model="ruleForm['caseType']" placeholder="请选择案件类型" multiple>
<el-option v-for="item in caseTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in caseTypeOptions" :key="item.id" :label="item.modelName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-col> -->
<el-col :span="24">
<el-form-item label="原子指标" prop="atomicIndexList">
<el-button type="primary" @click="handleSelectAtomic"></el-button>
@ -153,7 +158,7 @@
import SelectAtomic from '@/views/ruleEngine/indexRule/components/SelectAtomic.vue'
import CustomLogic from '@/views/ruleEngine/indexRule/components/CustomLogic.vue'
import { addOrUpdIndex } from '@/api/indexRule'
import { queryModelList } from '@/api/indexRule/index'
export default {
name: 'EditRule',
components: { CustomLogic, SelectAtomic },
@ -167,7 +172,7 @@ export default {
//
activeStep: 0,
//
caseTypeOptions: JSON.parse(sessionStorage.getItem('case_type')),
caseTypeOptions: [],
//
indexTypeOptions: JSON.parse(sessionStorage.getItem('index_type')),
//
@ -197,6 +202,8 @@ export default {
atomicIndex: [{ required: true, message: '原子指标不能为空!', trigger: 'blur' }],
indexRule: [{ required: true, message: '指标说明不能为空!', trigger: 'blur' }]
},
modelName: '',
modelId: '',
//
isEdit: false
//
@ -204,10 +211,16 @@ export default {
},
methods: {
//
show(data, isEdit) {
show(data, isEdit, item) {
if (item.id) {
this.modelName = item.modelName
this.modelId = item.id
}
this.activeStep = 0
this.isEdit = isEdit
this.drawerOption.show = true
this.getModelList()
this.$nextTick(() => {
const _this = this
_this.ruleForm = isEdit ? JSON.parse(JSON.stringify(data)) : {}
@ -219,6 +232,13 @@ export default {
}
})
},
getModelList() {
queryModelList({}, 1, 9999).then(res => {
if (res.code === 200) {
this.caseTypeOptions = res.data.records
}
})
},
delItem(index) {
this.ruleForm['atomicIndexList'].splice(index, 1)
},
@ -277,9 +297,10 @@ export default {
if (params.ruleConditionGroupList) {
this.$set(this.ruleForm, 'indexRule', params)
}
if (this.$baseLodash.isArray(this.ruleForm['caseType'])) {
this.ruleForm['caseType'] = this.ruleForm['caseType'].join(',')
}
// if (this.$baseLodash.isArray(this.ruleForm['caseType'])) {
// this.ruleForm['caseType'] = this.ruleForm['caseType'].join(',')
// }
this.ruleForm['caseType'] = this.modelId
const { code, msg } = await addOrUpdIndex(this.ruleForm)
code === 200 ? (this.isEdit ? this.$baseMessage.success(msg || '编辑成功!') : this.$baseMessage.success(msg || '新增成功!')) : (this.isEdit ? this.$baseMessage.error(msg || '新增失败!') : this.$baseMessage.error(msg || '新增失败!'))
this.drawerOption.show = false

@ -76,7 +76,7 @@ export default {
{ label: '指标名称', model: 'name', type: 'input' },
{ label: '指标类别', model: 'indexType', type: 'select', option: JSON.parse(sessionStorage.getItem('index_type')) },
// { label: '', model: 'doer', type: 'input' },
{ label: '案件类型', model: 'caseType', type: 'select', option: JSON.parse(sessionStorage.getItem('case_type')) },
// { label: '', model: 'caseType', type: 'select', option: JSON.parse(sessionStorage.getItem('case_type')) },
{ label: '原子指标', model: 'atomicIndexName', type: 'input' }
],
//

@ -0,0 +1,89 @@
<template>
<cs-drawer
:drawer-option="drawerOption"
@onReset="handleReset"
@onSubmit="handleSubmit"
>
<template slot="content">
<div class="AddModel">
<el-form ref="myForm" :model="ruleForm" :rules="rules" label-width="120px">
<el-form-item label="模型名称" prop="modelName">
<el-input v-model="ruleForm['modelName']" placeholder="请输入模型名称" />
</el-form-item>
<el-form-item label="模型说明" prop="modelDesc">
<el-input v-model="ruleForm['modelDesc']" type="textarea" :rows="5" placeholder="请输入模型说明" />
</el-form-item>
<el-form-item label="规则说明" prop="scoringRules">
<el-input v-model="ruleForm['scoringRules']" type="textarea" :rows="5" placeholder="请输入规则说明" />
</el-form-item>
</el-form>
</div>
</template>
</cs-drawer>
</template>
<script>
import { saveScoringModel } from '@/api/indexRule'
export default {
name: 'AddModel',
data() {
return {
drawerOption: {
show: false,
title: '案件模型',
isClosed: true,
width: '40%'
},
ruleForm: {
modelName: '',
modelDesc: '',
scoringRules: ''
},
rules: {
modelName: [{ required: true, message: '请输入模型名称', trigger: 'change' }],
modelDesc: [{ required: true, message: '请输入模型说明', trigger: 'change' }],
scoringRules: [{ required: true, message: '请输入规则说明', trigger: 'change' }],
}
}
},
methods: {
//
show() {
this.drawerOption.show = true
this.ruleForm = {
modelName: '',
modelDesc: '',
scoringRules: ''
}
},
//
handleReset() {
this.$refs.myForm.resetFields()
this.$refs.myForm.clearValidate()
},
handleSubmit() {
this.$refs.myForm.validate(valid => {
if (valid) {
const loading = this.$baseLoading(1, '保存中...')
saveScoringModel(this.ruleForm).then(res => {
loading.close()
if (res.code === 200) {
this.drawerOption.show = false
this.$emit('addOk')
this.$baseMessage.success('新增成功')
}
}).catch(() => { loading.close() })
}
})
}
}
}
</script>
<style scoped lang="scss">
.AddModel {
}
</style>

@ -0,0 +1,511 @@
<template>
<cs-drawer
:drawer-option="drawerOption"
>
<template slot="content">
<div ref="logic" class="logic-content">
<div v-for="(item, index) in ruleConditionGroupList" :key="index">
<div v-if="index !== 0" class="flex-row group-logic-content">
<i class="active-point" />
<el-radio-group v-model="groupLogic" class="group-logic">
<el-radio-button
v-for="logic in logicSymbolOptions"
:key="logic.value"
:label="logic.value"
>
{{ logic.label }}
</el-radio-button>
</el-radio-group>
</div>
<div class="group">
<span class="group-title">影响案件指标的原子指标项目</span>
<el-radio-group v-model="item.rowLogic" disabled class="row-logic">
<el-radio-button
v-for="logic in logicSymbolOptions"
:key="logic.value"
:label="logic.value"
>
{{ logic.label }}
</el-radio-button>
</el-radio-group>
<div v-for="(subItem, subIndex) in item.ruleConditionList" :key="subIndex">
<div class="flex-row row-content">
<span class="row-line" />
<el-select
v-model="subItem.atomicIndexId"
placeholder="请选择"
disabled
style="width: 300px"
>
<el-option
v-for="option in atomicIndexData"
:key="option.id"
:label="option.name"
:value="option.id"
/>
</el-select>
<el-select
v-model="subItem.relationalSymbol"
placeholder="请选择"
disabled
style="width: 150px;margin-left: 20px"
>
<el-option
v-for="option in symbolOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
<div v-if="subItem.relationalSymbol==='3' && subItem.indexSource ==='3'">
<el-input v-model="modelText" style="width: 80px;margin-left: 20px" readonly />
<el-select
v-model="subItem.operator"
placeholder="请选择"
disabled
style="width: 100px;margin-left: 20px"
>
<el-option
v-for="option in operatorList"
:key="option"
:label="option"
:value="option"
/>
</el-select>
<el-input-number v-model="subItem.value" disabled style="width: 150px;margin-left: 20px" :min="1" />
<!-- <el-input v-model="subItem.value" type="number" /> -->
</div>
</div>
<div v-if="subItem.indexSource === '5'" class="row-sku">
<div class="row-sku-top">
<el-radio-group v-model="subItem.logic" disabled class="group-logic">
<el-radio-button
v-for="logic in logicSymbolOptions"
:key="logic.value"
:label="logic.value"
>
{{ logic.label }}
</el-radio-button>
</el-radio-group></div>
<div v-for="(items,i) in subItem.operandUnitList" :key="i">
<div class="flex-row row-content">
<!-- <span class="row-line" /> -->
<el-select
v-model="items.leftOperand.propertyKey"
placeholder="请选择"
disabled
style="width: 200px"
>
<el-option
v-for="option in atomicIndexAttributeScope[subItem.atomicIndexId]"
:key="option.value"
:label="option.value"
:value="option.value"
/>
</el-select>
<el-select
v-if="items.leftOperand.propertyKey"
v-model="items.leftOperand.aggregateType"
placeholder="请选择"
disabled
style="width: 100px;margin-left: 20px;"
>
<el-option
v-for="option in getOptionList(items.leftOperand.propertyKey,subItem.atomicIndexId,'aggregateList')"
:key="option.key"
:label="option.value"
:value="option.key"
/>
</el-select>
<el-select
v-if="items.leftOperand.propertyKey"
v-model="items.operator"
placeholder="请选择"
disabled
style="width: 100px;margin-left: 20px;"
>
<el-option
v-for="option in getOptionList(items.leftOperand.propertyKey,subItem.atomicIndexId,'operatorList')"
:key="option"
:label="option"
:value="option"
/>
</el-select>
<el-select
v-if="items.leftOperand.propertyKey"
v-model="items.rightOperand.operandType"
placeholder="请选择"
disabled
style="width: 100px;margin-left: 20px;"
>
<el-option
key="6"
label="值"
value="6"
/> <el-option
key="5"
label="原子指标"
value="5"
/>
</el-select>
<div v-if="items.rightOperand.operandType ==='6'" style="margin-left: 20px;">
<el-input v-if="getAttrValueType(items.leftOperand.propertyKey,subItem.atomicIndexId) ==='1'" v-model="items.rightOperand.value" readonly placeholder="请输入" />
<el-input v-if="getAttrValueType(items.leftOperand.propertyKey,subItem.atomicIndexId) ==='2'" v-model="items.rightOperand.value" type="number" placeholder="请输入" />
<el-date-picker
v-if="getAttrValueType(items.leftOperand.propertyKey,subItem.atomicIndexId) ==='3'"
v-model="items.rightOperand.value"
disabled
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
type="date"
placeholder="选择日期"
/>
</div>
<el-select
v-if="items.rightOperand.operandType ==='5'"
v-model="items.rightOperand.atomicIndexId"
style="margin-left: 20px;width: 200px;"
placeholder="请选择"
disabled
>
<el-option
v-for="option in atomicIndexData"
:key="option.id"
:label="option.name"
:value="option.id"
/>
</el-select>
<el-select
v-if="items.rightOperand.operandType ==='5'"
v-model="items.rightOperand.propertyKey"
placeholder="请选择"
disabled
style="width: 150px;margin-left: 20px;"
>
<el-option
v-for="option in atomicIndexAttributeScope[items.rightOperand.atomicIndexId]"
:key="option.value"
:label="option.value"
:value="option.value"
/>
</el-select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
</cs-drawer>
</template>
<script>
import mixin from '@/views/mixin'
import { listAtomicIndexAttributeScope } from '@/api/indexRule'
export default {
name: 'DetailsModel',
mixins: [mixin],
data() {
return {
drawerOption: {
show: false,
hiddenFooter: true,
title: '详情',
isClosed: true,
width: '40%'
},
atomicIndexData: [],
indexRule: undefined,
//
ruleConditionGroupList: [
{ rowLogic: '2', ruleConditionList: [{ atomicIndexId: '', indexSource: '', logic: '2', relationalSymbol: '', operator: '>', value: '', operandUnitList: [] }] }
],
groupLogic: '2',
modelText: '数量',
atomicIndexAttributeScope: {},
operatorList: ['>', '>=', '<', '<=', '=', '!='],
//
logicSymbolOptions: JSON.parse(sessionStorage.getItem('logic_symbol'))
//
// symbolOptions: JSON.parse(sessionStorage.getItem('judge_result'))
}
},
computed: {
symbolOptions() {
const list = JSON.parse(sessionStorage.getItem('judge_result'))
// eslint-disable-next-line no-const-assign
for (let i = 0; i < list.length; i++) {
if (list[i].label === '未知') {
list.splice(i, 1)
}
}
return list
}
},
mounted() {
},
methods: {
show(row) {
this.atomicIndexData = row.atomicIndexList
this.indexRule = row.indexRule
this.drawerOption.show = true
this.init()
},
init() {
this.getAtomicIndexAttributeScope()
if (!this.indexRule.ruleConditionGroupList || this.indexRule.ruleConditionGroupList.length === 0) return
this.groupLogic = this.indexRule.groupLogic
this.ruleConditionGroupList = this.indexRule.ruleConditionGroupList
this.ruleConditionGroupList.map((item) => {
item.ruleConditionList.map((subItem) => {
if (!this.getListValueFlag(subItem.atomicIndexId)) {
subItem.atomicIndexId = ''
subItem.indexSource = ''
subItem.operandUnitList = []
}
})
})
},
//
getIndexSource(val) {
for (const item of this.atomicIndexData) {
if (val === item.id) {
return item.indexSource
}
}
},
//
async getAtomicIndexAttributeScope() {
const list = []
for (const item of this.atomicIndexData) {
list.push(item.id)
}
const res = await listAtomicIndexAttributeScope(list)
if (res.code === 200) {
this.atomicIndexAttributeScope = res.data
}
},
getAttrValueType(value, atomicIndexId) {
if (value && atomicIndexId) {
const list = this.atomicIndexAttributeScope[atomicIndexId]
for (const item of list) {
if (item.value === value) {
return item.valueType
}
}
}
},
//
getOptionList(value, atomicIndexId, type) {
if (value && atomicIndexId) {
const list = this.atomicIndexAttributeScope[atomicIndexId]
for (const item of list) {
if (item.value === value) {
return item[type]
}
}
}
},
selectAtomic(val, subItem) {
this.getAtomicIndexAttributeScope(val)
subItem.indexSource = this.getIndexSource(val)
this.$set(subItem, 'relationalSymbol', '')
this.$set(subItem, 'operator', '')
this.$set(subItem, 'value', '')
},
selectRelational(val, subItem) {
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) {
items.leftOperand.valueType = this.getAttrValueType(val, id)
this.$set(items.leftOperand, 'aggregateType', '')
this.$set(items, 'rightOperand', {
atomicIndexId: '',
value: '',
valueType: '',
operandType: '',
propertyKey: ''
})
this.$set(items, 'operator', '')
},
//
addOperandUnitList(index, subIndex) {
this.ruleConditionGroupList[index].ruleConditionList[subIndex].operandUnitList.push({
leftOperand: {
atomicIndexId: '',
operandType: '5'
},
rightOperand: {
atomicIndexId: '',
value: '',
valueType: '',
operandType: '',
propertyKey: ''
}
})
},
//
handleAdd() {
this.gridOptions.data.push({
atomicIndexName: '',
relationalSymbol: '',
atomicIndexName2: '',
indexResult: ''
})
},
getListValueFlag(val) {
let flag = false
for (const item of this.atomicIndexData) {
if (item.id === val) {
flag = true
}
}
return flag
},
//
handleAddRow(val) {
val.ruleConditionList.push({
atomicIndexId: '', indexSource: '', rowLogic: '', relationalSymbol: '', operator: '>', value: '', operandUnitList: []
})
},
//
handleAddGroup(index) {
if (this.ruleConditionGroupList.length > 1) return
this.ruleConditionGroupList.splice(index, 0, {
rowLogic: '2', ruleConditionList: [{ atomicIndexId: '', indexSource: '', rowLogic: '', relationalSymbol: '', operator: '>', value: '', operandUnitList: [] }]
})
},
//
handleDelGroup(item) {
if (this.ruleConditionGroupList.length === 1) {
this.$baseMessage.error('至少保留一条数据!')
return
}
this.ruleConditionGroupList.splice(this.ruleConditionGroupList.indexOf(item), 1)
},
//
handleRowClick(item, subItem) {
item.ruleConditionList.splice(item.ruleConditionList.indexOf(subItem), 1)
},
delItem(item, subItem) {
item.operandUnitList.splice(item.operandUnitList.indexOf(subItem), 1)
},
//
validate() {
let valid = true
this.ruleConditionGroupList.map((item) => {
item.ruleConditionList.map((subItem) => {
if (!subItem.atomicIndexId || !subItem.relationalSymbol) {
valid = false
}
})
})
if (valid) {
return {
groupLogic: this.groupLogic,
ruleConditionGroupList: this.ruleConditionGroupList
}
} else {
this.$baseMessage.error('请选择原子指标和关系符号')
}
}
}
}
</script>
<style scoped lang="scss">
.logic-content {
padding: 10px;
box-sizing: border-box;
margin-top: 20px;
.group {
border: 1px dashed #999999;
position: relative;
padding-bottom: 40px;
.group-title {
position: absolute;
top: -10px;
left: 10px;
background: #ffffff;
padding: 0 8px;
}
.row-logic {
position: absolute;
top: -15px;
left: 230px;
background: #ffffff;
}
.row-content {
margin: 30px 0 16px 0;
align-items: center;
.row-line {
width: 50px;
height: 1px;
border-bottom: 1px dashed #999999;
}
}
.row-button {
position: absolute;
bottom: -15px;
left: 30px;
}
.group-button {
position: absolute;
bottom: -15px;
left: 170px;
}
.group-del {
position: absolute;
bottom: -15px;
left: 310px;
}
.row-sku {
background: rgba(55,99,255,0.05);
margin: 0 42px;
padding: 18px;
.row-sku-top {
// padding-left: 50px;
span {
font-size: 14px;
color: #3763FF;
margin-left: 4px;
cursor: pointer;
margin-right: 16px;
}
}
}
}
.group-logic-content {
padding: 30px 0;
border-left: 1px dashed #999999;
position: relative;
.active-point {
width: 4px;
height: 4px;
border-radius: 2px;
background: $base-color-default;
position: absolute;
left: -2px;
top: 45px;
}
.group-logic {
margin-left: 10px;
}
}
}
</style>

@ -0,0 +1,104 @@
<template>
<cs-drawer
:drawer-option="drawerOption"
@onReset="handleReset"
@onSubmit="handleSubmit"
>
<template slot="content">
<div class="EditModel">
<el-form ref="myForm" :model="ruleForm" :rules="rules" label-width="120px">
<el-form-item label="模型名称" prop="modelName">
<el-input v-model="ruleForm['modelName']" placeholder="请输入模型名称" />
</el-form-item>
<el-form-item label="模型说明" prop="modelDesc">
<el-input v-model="ruleForm['modelDesc']" type="textarea" :rows="5" placeholder="请输入模型说明" />
</el-form-item>
<el-form-item label="规则说明" prop="scoringRules">
<el-input v-model="ruleForm['scoringRules']" type="textarea" :rows="5" placeholder="请输入规则说明" />
</el-form-item>
</el-form>
</div>
</template>
</cs-drawer>
</template>
<script>
import { updateScoringModel,copyScoringModel } from '@/api/indexRule'
export default {
name: 'EditModel',
data() {
return {
drawerOption: {
show: false,
isClosed: true,
title: '案件模型',
width: '40%'
},
ruleForm: {
modelName: '',
modelDesc: '',
scoringRules: ''
},
isCopy: false,
rules: {
modelName: [{ required: true, message: '请输入模型名称', trigger: 'change' }],
modelDesc: [{ required: true, message: '请输入模型说明', trigger: 'change' }],
scoringRules: [{ required: true, message: '请输入规则说明', trigger: 'change' }]
}
}
},
methods: {
//
show(data, type) {
this.drawerOption.show = true
if (type === 'copy') {
this.isCopy = true
} else {
this.isCopy = false
}
this.ruleForm = {
...data
}
},
//
handleReset() {
this.$refs.myForm.resetFields()
this.$refs.myForm.clearValidate()
},
handleSubmit() {
this.$refs.myForm.validate(valid => {
if (valid) {
const loading = this.$baseLoading(1, '保存中...')
if (this.isCopy) {
copyScoringModel(this.ruleForm).then(res => {
loading.close()
if (res.code === 200) {
this.drawerOption.show = false
this.$emit('editOk')
this.$baseMessage.success('复制成功')
}
}).catch(() => { loading.close() })
} else {
updateScoringModel(this.ruleForm).then(res => {
loading.close()
if (res.code === 200) {
this.drawerOption.show = false
this.$emit('editOk')
this.$baseMessage.success('编辑成功')
}
}).catch(() => { loading.close() })
}
}
})
}
}
}
</script>
<style scoped lang="scss">
.EditModel {
}
</style>

@ -0,0 +1,391 @@
<template>
<div class="scoringModel">
<div class="case_list">
<div v-for="(item,index) in caseList" :key="index" class="case_item" :class="[selectId === item.id ?'actived':'']" @click="selectCase(item)">
<span style="width: 180px;">{{ item.modelName.slice(0,8) }}</span>
<el-popover
:ref="`popover-${index}`"
append-to-body
placement="bottom"
width="80"
trigger="click"
>
<template #reference>
<div :id="'popover-btn-' + index" class="circle_list">
<span class="circle" />
<span class="circle" />
<span class="circle" />
</div>
</template>
<div class="scoringModel-operate">
<div class="operate-item" @click="editModel(item)">
<img src="../../../assets/common/edit.png" alt="">
<span>编辑</span>
</div>
<div class="operate-item" @click="copyModel(item)">
<img src="../../../assets/common/copy.png" alt="">
<span>复制</span>
</div>
<div class="operate-item" @click="delModel(item)">
<img src="../../../assets/common/del.png" alt="">
<span>删除</span>
</div>
</div>
</el-popover>
</div>
<div class="add_btn" @click="addModel">
<i class="el-icon-circle-plus-outline" style="margin-right: 8px;" />
<span>新增</span>
</div>
</div>
<div ref="htmlContent" class="content">
<cs-search title="赋分模型" :data="searchData" :span="6" direction="row" @onSearch="onSearch" @getData="onSearch" />
<div class="index-content">
<div class="header">
<el-radio-group v-model="type" size="large" @change="handleChange">
<el-radio-button v-for="(item,index) in indexTypeList" :key="index" :label="item.value">{{ item.label }}</el-radio-button>
</el-radio-group>
<el-button type="primary" icon="el-icon-circle-plus-outline" style="position: absolute;right: 24px;top: 12px;" @click="handleAdd"></el-button>
<vxe-grid v-bind="gridOptions" style="margin-top: 20px">
<template #operate="{row}">
<el-tooltip class="item" effect="dark" content="编辑" placement="top-start">
<el-button type="text" icon="el-icon-edit" title="编辑" @click="handleEdit(row)" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="删除" placement="top-start">
<el-button type="text" icon="el-icon-delete" style="color: red" title="删除" @click="handleDel(row)" />
</el-tooltip>
</template>
<template #name="{row}">
<el-link type="primary" @click="opendetails(row)">{{ row.name }}</el-link>
</template>
</vxe-grid>
<div style="text-align: center">
<cs-page
:page.sync="queryForm.page"
:limit.sync="queryForm.size"
:total="queryForm.total"
@pagination="fetchData"
/>
</div>
</div>
</div>
<!-- <div class="main-content">
<div class="details">
1111
<div class="contract">
<i class="el-icon-d-arrow-right contract-icon" />
</div>
</div>
</div> -->
</div>
<AddModel ref="AddModelRef" @addOk="getModelList" />
<EditModel ref="EditModelRef" @editOk="getModelList" />
<DetailsModel ref="DetailsModelRef" />
<!--编辑弹窗-->
<edit-rule ref="edit" @reloadData="fetchData" />
<!--变更弹窗-->
<change-rules ref="change" />
</div>
</template>
<script>
import mixin from '@/views/mixin'
import AddModel from './compontents/AddModel.vue'
import EditModel from './compontents/EditModel.vue'
import DetailsModel from './compontents/DetailsModel.vue'
import EditRule from '@/views/ruleEngine/indexRule/components/EditRule.vue'
import ChangeRules from '@/views/ruleEngine/indexRule/components/ChangeRules.vue'
import { queryModelList, queryIndexData, deleteModelIndex, deleteScoringModel } from '@/api/indexRule/index'
export default {
name: 'ScoringModel',
components: {
AddModel,
ChangeRules,
EditRule,
EditModel,
DetailsModel
},
mixins: [mixin],
data() {
return {
caseList: [
],
dialogVisible: false,
indexType: '',
selectId: '',
indexTypeList: [
{
label: '共性指标',
value: '1'
},
{
label: '入罪指标',
value: '2'
},
{
label: '出罪指标',
value: '3'
}
],
//
searchData: [
{ label: '指标名称', model: 'name', type: 'input' },
{ label: '原子指标', model: 'atomicIndexName', type: 'input' }
],
modelName: '',
type: '',
//
gridOptions: {
...mixin.data().gridOptions,
columns: [
{ title: '序号', type: 'seq', width: 80 },
{ title: '指标名称', field: 'name', slots: { default: 'name' }, align: 'left' },
{ title: '指标类别', field: 'indexTypeName', width: '150px' },
{ title: '指标分数', field: 'indexScore', width: '150px', sortable: true },
{ title: '原子指标数量', field: 'atomicIndexNum', width: '150px' },
{ title: '最新时间', field: 'updateTime', width: '150px' },
{ title: '操作', slots: { default: 'operate' }, width: '150px' }
],
data: []
}
}
},
mounted() {
this.getModelList()
this.tableHeight(400)
},
methods: {
//
handleDel(row) {
this.$baseConfirm('确定要删除吗?', null, async() => {
const { code, msg } = await deleteModelIndex(row.id)
code === 200 ? this.$baseMessage.success(msg || '删除成功!') : this.$baseMessage.error(msg || '删除失败!')
this.fetchData()
})
},
addModel() {
this.$refs.AddModelRef.show()
},
getModelList() {
queryModelList({}, 1, 9999).then(res => {
if (res.code === 200) {
this.caseList = res.data.records
if (this.caseList.length > 0) {
this.selectCase(this.caseList[0])
}
}
})
},
//
fetchData() {
queryIndexData({ ...this.searchFormData, caseType: this.selectId, indexType: this.indexType }, this.queryForm.page, this.queryForm.size).then(res => {
this.gridOptions.data = res.data.result
this.queryForm.total = res.data.total
})
},
//
handleAdd() {
this.$refs.edit.show(undefined, false, this.modelInfo)
},
//
handleChange(val) {
this.indexType = val
this.fetchData()
},
//
handleEdit(row) {
this.$refs.edit.show(row, true, this.modelInfo)
},
//
selectCase(item) {
this.selectId = item.id
this.modelInfo = {
modelName: item.modelName,
id: item.id
}
this.fetchData()
},
//
editModel(item) {
this.$refs.EditModelRef.show(item)
},
//
delModel(item) {
this.$baseConfirm('确定要删除吗?', null, async() => {
const { code, msg } = await deleteScoringModel({ id: item.id })
code === 200 ? this.$baseMessage.success(msg || '删除成功!') : this.$baseMessage.error(msg || '删除失败!')
this.getModelList()
})
},
//
copyModel(item) {
this.$refs.EditModelRef.show(item, 'copy')
},
opendetails(row) {
this.$refs.DetailsModelRef.show(row)
},
//
onSearch(data, callback) {
this.searchFormData = Object.assign({}, data)
this.queryForm.page = 1
this.fetchData()
if (callback) callback(true)
}
}
}
</script>
<style scoped lang="scss">
.scoringModel {
display: flex;
height: 100%;
.case_list {
width: 216px;
height: 894px;
background: #FFFFFF;
border-radius: 8px 8px 8px 8px;
margin-right: 16px;
display: flex;
flex-direction: column;
align-items: center;
padding: 24px;
height: calc(100vh - 200px);
.case_item {
width: 168px;
// height: 53px;
background: #FFFFFF;
border-radius: 6px 6px 6px 6px;
border: 1px solid #D9D9D9;
padding: 16px;
display: flex;
// justify-content: space-around;
align-items: center;
cursor: pointer;
margin-bottom: 16px;
span {
font-size: 16px;
color: #333333;
}
.circle_list {
display: flex;
flex-direction: column;
.circle {
width: 3px;
height: 3px;
background: #333333;
border-radius: 50%;
margin-top: 2px;
}
}
}
.actived {
background: #3763FF;
span {
color: #FFFFFF;
}
.circle {
background: #FFFFFF !important;
}
}
.add_btn {
width: 168px;
// height: 53px;
background: #FFFFFF;
border-radius: 6px 6px 6px 6px;
border: 1px solid #3763FF;
padding: 16px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 16px;
color: #3763FF;
}
}
.content {
flex: 1;
// height: 100%;
.index-content {
border-radius: 8px;
background: white;
padding: 20px;
box-sizing: border-box;
margin-top: 10px;
height: calc(100vh - 275px);
flex: 1;
.header {
position: relative;
}
}
.main-content {
display: flex;
width: 100%;
.details {
width: 408px;
background: #FFFFFF;
border-radius: 6px 6px 6px 6px;
margin-left: 16px;
margin-top: 10px;
position: relative;
.contract {
position: absolute;
top: 50%;
left: -18px;
cursor: pointer;
width: 20px;
border-bottom: 10px solid #fff;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
height: 0;
transform: rotate(-90deg);
/* 向左旋转 90 度 */
transform-origin: center center;
.contract-icon {
transform: rotate(90deg);
cursor: pointer;
padding-left:5px ;
}
}
}
}
}
}
</style>
<style lang="scss" >
.scoringModel-operate{
.operate-item {
display: flex;
font-size: 16px;
color: #333333;
margin: 12px 0px;
justify-content: space-around;
align-items: center;
cursor: pointer;
img {
width: 17px;
height: 17px;
// margin-right: 12px;
}
}
}
</style>
Loading…
Cancel
Save