You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1448 lines
54 KiB
1448 lines
54 KiB
<template> |
|
<div class="container"> |
|
<el-row :gutter="20"> |
|
<el-col :span="4"> |
|
<div class="menu"> |
|
<div @click="handleChangeClass()" :active="!query.classId"> |
|
全部 |
|
</div> |
|
<div |
|
v-for="(item, index) in classes" |
|
:key="index" |
|
@click="handleChangeClass(item.id)" |
|
:active="query.classId === item.id" |
|
> |
|
<span :title="item.name">{{ item.name }}</span> |
|
<span class="ml-8 text-primary text-bold">{{ |
|
item.size |
|
}}</span> |
|
</div> |
|
</div> |
|
</el-col> |
|
<el-col :span="20"> |
|
<el-form :label-width="140"> |
|
<el-row> |
|
<el-col :span="9"> |
|
<el-form-item label="模型名称"> |
|
<el-input |
|
placeholder="请输入" |
|
v-model="query.modelName" |
|
clearable |
|
/> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="8"> |
|
<el-form-item label="分发方式"> |
|
<el-select |
|
v-model="query.distributionMethod" |
|
clearable |
|
> |
|
<el-option |
|
v-for="item in dict.distributionMethod" |
|
:key="item.id" |
|
:label="item.dictLabel" |
|
:value="item.dictValue" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
</el-form> |
|
<div class="flex between mb-20"> |
|
<el-button type="primary" @click="handleAdd"> |
|
<template #icon> |
|
<icon name="el-icon-Plus" /> |
|
</template> |
|
添加模型</el-button |
|
> |
|
<div> |
|
<el-button type="primary" @click="getList"> |
|
<template #icon> |
|
<icon name="el-icon-Search" /> |
|
</template> |
|
查询</el-button |
|
> |
|
<el-button @click="reset">重置</el-button> |
|
</div> |
|
</div> |
|
<div> |
|
<el-row :gutter="17"> |
|
<el-col |
|
:span="8" |
|
v-for="item in list" |
|
:key="item" |
|
class="mb-18" |
|
> |
|
<div class="model-card" @click="openDetail(item)"> |
|
<div class="flex v-center"> |
|
<div |
|
class="model-icon" |
|
:style="{ background: item.iconColor }" |
|
> |
|
<icon |
|
:name="item.icon" |
|
:size="76" |
|
v-if="item.icon" |
|
/> |
|
</div> |
|
<div |
|
class="model-card-content" |
|
style="width: calc(100% - 76px)" |
|
> |
|
<div> |
|
<div class="row"> |
|
<div class="col col-24"> |
|
<label>模型名称</label> |
|
<span |
|
class="text-nowrap" |
|
:title="item.modelName" |
|
>{{ |
|
item.modelName |
|
}}</span |
|
> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col col-24"> |
|
<label>模型分类</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.modelType, |
|
item.modelType |
|
) |
|
}}</span> |
|
</div> |
|
</div> |
|
<div class="col col-24"> |
|
<label>活跃时间</label> |
|
<span>{{ |
|
item.updateTime |
|
}}</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</el-col> |
|
</el-row> |
|
<el-empty description="无数据" v-if="list.length === 0" /> |
|
<div class="flex end mt-8"> |
|
<el-pagination |
|
@size-change="getList" |
|
@current-change="getList" |
|
:page-sizes="[12, 24, 48]" |
|
v-model:page-size="query.size" |
|
v-model:current-page="query.current" |
|
layout="total, sizes, prev, pager, next" |
|
:total="total" |
|
v-if="list.length" |
|
> |
|
</el-pagination> |
|
</div> |
|
</div> |
|
</el-col> |
|
</el-row> |
|
</div> |
|
|
|
<el-dialog |
|
:title="mode === 'add' ? '添加模型' : '编辑模型'" |
|
v-model="show" |
|
top="4vh" |
|
> |
|
<el-form label-width="130" ref="formRef" :model="form"> |
|
<el-form-item |
|
label="模型名称" |
|
prop="modelName" |
|
:rules="{ |
|
required: true, |
|
message: '请输入模型名称', |
|
trigger: ['blur'], |
|
}" |
|
> |
|
<el-input |
|
placeholder="请输入模型名称" |
|
style="width: 340px" |
|
v-model="form.modelName" |
|
/> |
|
</el-form-item> |
|
<el-form-item |
|
label="模型图标" |
|
prop="icon" |
|
:rules="{ |
|
required: true, |
|
message: '请选择模型图标', |
|
}" |
|
> |
|
<model-icon-picker |
|
v-model:ico="form.icon" |
|
v-model:color="form.iconColor" |
|
/> |
|
</el-form-item> |
|
<el-form-item |
|
label="模型描述" |
|
prop="remarks" |
|
:rules="{ |
|
required: true, |
|
message: '请输入模型描述', |
|
}" |
|
> |
|
<el-input |
|
type="textarea" |
|
:autosize="{ minRows: 4 }" |
|
v-model="form.remarks" |
|
placeholder="请输入" |
|
/> |
|
</el-form-item> |
|
<el-form-item |
|
label="建模方式" |
|
prop="modelingMethod" |
|
:rules="{ |
|
required: true, |
|
message: '请选择建模方式', |
|
}" |
|
> |
|
<el-select v-model="form.modelingMethod" style="width: 340px"> |
|
<el-option |
|
v-for="item in dict.modelingMethod" |
|
:key="item.dictValue" |
|
:label="item.dictLabel" |
|
:value="item.dictValue" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<template v-if="form.modelingMethod === '2'"> |
|
<el-form-item |
|
label="模型结果表" |
|
prop="clueTableName" |
|
:rules="{ |
|
required: true, |
|
message: '请选择', |
|
}" |
|
> |
|
<el-select |
|
v-model="form.clueTableName" |
|
style="width: 340px" |
|
@change="handleSelectClueTableName" |
|
> |
|
<el-option |
|
v-for="item in clueMappingData" |
|
:key="item.tableName" |
|
:label="item.tableName" |
|
:value="item.tableName" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item |
|
label="结果字段映射" |
|
:rules="{ |
|
required: true, |
|
message: '请选择', |
|
}" |
|
> |
|
<el-row :gutter="10" style="width: 100%"> |
|
<el-col :span="11"> |
|
<div class="field-table-title"> |
|
数据督察预警问题表 |
|
</div> |
|
<el-table size="small" :data="modelClueColumns"> |
|
<el-table-column |
|
label="字段名" |
|
prop="fieldName" |
|
width="150" |
|
> |
|
<template #default="{ row }"> |
|
<div |
|
:class=" |
|
row.required |
|
? 'text-danger' |
|
: '' |
|
" |
|
> |
|
{{ row.fieldName }} |
|
</div> |
|
</template> |
|
</el-table-column> |
|
<el-table-column |
|
label="字段类型" |
|
prop="fieldType" |
|
width="80" |
|
align="center" |
|
/> |
|
<el-table-column |
|
label="描述" |
|
prop="fieldDesc" |
|
show-overflow-tooltip |
|
/> |
|
</el-table> |
|
</el-col> |
|
<el-col :span="2"> |
|
<div |
|
style="margin-top: 104px" |
|
class="text-center field-arrow" |
|
> |
|
→ |
|
</div> |
|
<div class="text-center field-arrow text-danger"> |
|
→ |
|
</div> |
|
<div class="text-center field-arrow">→</div> |
|
<div class="text-center field-arrow">→</div> |
|
<div class="text-center field-arrow">→</div> |
|
</el-col> |
|
<el-col :span="11"> |
|
<div class="field-table-title">模型结果表</div> |
|
<el-table |
|
size="small" |
|
:data="modelClueTargetColumns" |
|
class="field-table_target" |
|
> |
|
<el-table-column label="字段名" width="150"> |
|
<template #default="{ row }"> |
|
<el-select |
|
size="small" |
|
v-model="row.columnName" |
|
@change=" |
|
(val) => |
|
handleChangeColumn(val, row) |
|
" |
|
clearable |
|
> |
|
<el-option |
|
v-for="item in fields" |
|
:key="item.columnName" |
|
:value="item.columnName" |
|
:disabled=" |
|
modelClueTargetColumns.filter( |
|
(field) => |
|
field.columnName === |
|
item.columnName |
|
).length > 0 |
|
" |
|
> |
|
<span class="text-small">{{ |
|
item.columnName |
|
}}</span> |
|
<span |
|
v-if="item.columnComment" |
|
class="text-small" |
|
>-</span |
|
> |
|
<span class="text-small">{{ |
|
item.columnComment |
|
}}</span> |
|
</el-option> |
|
</el-select> |
|
</template> |
|
</el-table-column> |
|
<el-table-column |
|
label="字段类型" |
|
prop="dataType" |
|
width="80" |
|
align="center" |
|
/> |
|
<el-table-column |
|
label="描述" |
|
prop="columnComment" |
|
show-overflow-tooltip |
|
/> |
|
</el-table> |
|
</el-col> |
|
</el-row> |
|
</el-form-item> |
|
<el-form-item |
|
label="同步唯一字段名" |
|
prop="clueUniqueFieldName" |
|
:rules="{ |
|
required: true, |
|
message: '请选择', |
|
}" |
|
> |
|
<el-select |
|
style="width: 340px" |
|
v-model="form.clueUniqueFieldName" |
|
> |
|
<el-option |
|
v-for="item in fields" |
|
:key="item.columnName" |
|
:value="item.columnName" |
|
> |
|
<span class="text-small">{{ |
|
item.columnName |
|
}}</span> |
|
<span v-if="item.columnComment" class="text-small" |
|
>-</span |
|
> |
|
<span class="text-small">{{ |
|
item.columnComment |
|
}}</span> |
|
</el-option> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item |
|
label="预警内容生成器" |
|
prop="thingDescGeneration" |
|
:rules="{ |
|
required: true, |
|
message: '请输入', |
|
}" |
|
> |
|
<el-input |
|
v-model="form.thingDescGeneration" |
|
clearable |
|
type="textarea" |
|
placeholder="例:发现嫌疑人^name^,身份证号^idCode^的人,酒驾关8天" |
|
/> |
|
</el-form-item> |
|
<el-form-item |
|
label="同步周期" |
|
prop="clueCycle" |
|
:rules="{ |
|
required: true, |
|
message: '请选择同步周期', |
|
}" |
|
> |
|
<el-radio-group v-model="form.clueCycle" class="block"> |
|
<el-radio |
|
v-for="item in dict.distributionCycle" |
|
:key="item.dictCode" |
|
:value="item.dictValue" |
|
>{{ item.dictLabel }}</el-radio |
|
> |
|
</el-radio-group> |
|
<!-- <div class="flex ml-20" v-if="form.clueCycle"> |
|
<el-form-item |
|
label="周" |
|
prop="clueCycleDayOfWeek" |
|
label-width="80" |
|
:rules="{ |
|
required: true, |
|
message: '请选择', |
|
}" |
|
v-if="form.clueCycle === DistributionCycle.WEEKLY" |
|
> |
|
<el-select |
|
style="width: 120px" |
|
clearable |
|
v-model="form.clueCycleDayOfWeek" |
|
> |
|
<el-option value="MON">周一</el-option> |
|
<el-option value="TUE">周二</el-option> |
|
<el-option value="WED">周三</el-option> |
|
<el-option value="THU">周四</el-option> |
|
<el-option value="FRI">周五</el-option> |
|
<el-option value="SAT">周六</el-option> |
|
<el-option value="SUN">周日</el-option> |
|
</el-select> |
|
</el-form-item> |
|
</div> --> |
|
</el-form-item> |
|
<el-form-item |
|
label="机构映射" |
|
prop="clueDepartSource" |
|
:rules="{ |
|
required: true, |
|
message: '请选择机构映射', |
|
}" |
|
> |
|
<div class="flex gap"> |
|
<el-select |
|
style="width: 340px" |
|
v-model="form.clueDepartSource" |
|
clearable |
|
> |
|
<el-option |
|
v-for="item in dict.departMappingSource" |
|
:key="item.dictCode" |
|
:label="item.dictLabel" |
|
:value="item.dictValue" |
|
></el-option> |
|
</el-select> |
|
<el-button |
|
type="primary" |
|
plain |
|
@click="router.push('/system/dict')" |
|
>创建机构映射</el-button |
|
> |
|
</div> |
|
</el-form-item> |
|
</template> |
|
|
|
<el-form-item |
|
label="模型分类" |
|
prop="modelType" |
|
:rules="{ |
|
required: true, |
|
message: '请选择模型分类', |
|
}" |
|
> |
|
<el-radio-group v-model="form.modelType"> |
|
<el-radio |
|
v-for="item in dict.modelType" |
|
:key="item.dictCode" |
|
:value="item.dictValue" |
|
>{{ item.dictLabel }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
<el-divider /> |
|
|
|
<el-form-item |
|
label="模型类型" |
|
prop="classId" |
|
:rules="{ |
|
required: true, |
|
message: '请选择模型类型', |
|
}" |
|
v-if="form.modelType" |
|
> |
|
<el-select v-model="form.classId" style="width: 340px"> |
|
<el-option |
|
v-for="item in classes.filter( |
|
(item) => item.modelType === form.modelType |
|
)" |
|
:key="item.id" |
|
:label="item.name" |
|
:value="item.id" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item |
|
label="风险因素" |
|
:rules="{ |
|
required: true, |
|
message: '请选择风险因素', |
|
}" |
|
prop="riskScoreRuleId" |
|
v-if="form.modelType === '2'" |
|
> |
|
<el-tree-select |
|
class="flex-1" |
|
v-model="form.riskScoreRuleId" |
|
:data="treeOptions" |
|
clearable |
|
node-key="id" |
|
:props="{ |
|
label: 'riskName', |
|
}" |
|
placeholder="请选择风险因素" |
|
filterable |
|
style="width: 340px" |
|
/> |
|
</el-form-item> |
|
<el-form-item |
|
label="预警类型" |
|
prop="modelDataType" |
|
:rules="{ |
|
required: true, |
|
message: '请选择预警类型', |
|
}" |
|
> |
|
<el-radio-group v-model="form.modelDataType" class="block"> |
|
<el-radio value="1">{{ |
|
form.modelType === "2" ? "预警处置" : "预警问题" |
|
}}</el-radio> |
|
<el-radio value="2">提醒通知</el-radio> |
|
</el-radio-group> |
|
</el-form-item> |
|
<el-form-item |
|
label="说明" |
|
v-if="form.modelType === '2' && form.modelDataType === '1'" |
|
> |
|
<div style="line-height: 1.4"> |
|
通过情指行一体化平台进行处置反馈 |
|
</div> |
|
</el-form-item> |
|
<el-form-item |
|
label="分发方式" |
|
prop="distributionMethod" |
|
:rules="{ |
|
required: true, |
|
message: '请选择分发方式', |
|
}" |
|
v-if="form.modelType === '1' && form.modelDataType === '1'" |
|
> |
|
<el-radio-group v-model="form.distributionMethod" class="block"> |
|
<el-radio |
|
v-for="item in dict.distributionMethod" |
|
:key="item.dictCode" |
|
:value="item.dictValue" |
|
>{{ item.dictLabel }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
|
|
<template |
|
v-if=" |
|
form.modelType === '1' && |
|
form.modelDataType === '1' && |
|
form.distributionMethod === |
|
DistributionMethod.DIRECTLY_DISTRIBUTE |
|
" |
|
> |
|
<el-divider /> |
|
<el-form-item |
|
label="分发周期" |
|
prop="distributionCycle" |
|
:rules="{ |
|
required: true, |
|
message: '请选择分发周期', |
|
}" |
|
> |
|
<el-radio-group |
|
v-model="form.distributionCycle" |
|
class="block" |
|
> |
|
<el-radio |
|
v-for="item in dict.distributionCycle" |
|
:key="item.dictCode" |
|
:value="item.dictValue" |
|
>{{ item.dictLabel }}</el-radio |
|
> |
|
</el-radio-group> |
|
<div class="flex ml-20" v-if="form.distributionCycle"> |
|
<el-form-item |
|
label="周" |
|
prop="" |
|
label-width="80" |
|
:rules="{ |
|
required: true, |
|
message: '请选择', |
|
}" |
|
v-if=" |
|
form.distributionCycle === |
|
DistributionCycle.WEEKLY |
|
" |
|
> |
|
<el-select |
|
style="width: 120px" |
|
clearable |
|
v-model="form.distributionCycleDayOfWeek" |
|
> |
|
<el-option |
|
v-for="(item, index) in WEEKS" |
|
:key="index" |
|
:label="`周${item}`" |
|
:value="index" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item |
|
label="时间" |
|
prop="distributionCycleTime" |
|
label-width="80" |
|
:rules="{ |
|
required: true, |
|
message: '请选择', |
|
}" |
|
> |
|
<el-time-picker |
|
v-model="form.distributionCycleTime" |
|
placeholder="请选择" |
|
style="width: 120px" |
|
value-format="HH:mm:ss" |
|
clearable |
|
/> |
|
</el-form-item> |
|
</div> |
|
</el-form-item> |
|
|
|
<el-form-item |
|
label="业务类别" |
|
prop="businessTypeCode" |
|
:rules="{ |
|
required: true, |
|
message: '请选择业务类别', |
|
trigger: ['blur'], |
|
}" |
|
> |
|
<el-select |
|
v-model="form.businessTypeCode" |
|
style="width: 280px" |
|
> |
|
<el-option |
|
v-for="item in dict.businessType" |
|
:key="item.id" |
|
:label="item.dictLabel" |
|
:value="item.dictValue" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item |
|
label="涉嫌问题" |
|
prop="involveProblem" |
|
:rules="{ |
|
required: true, |
|
message: '请选择涉嫌问题', |
|
trigger: ['blur'], |
|
}" |
|
> |
|
<el-select |
|
v-model="form.involveProblem" |
|
multiple |
|
clearable |
|
style="width: 280px" |
|
> |
|
<el-option |
|
v-for="item in dict.suspectProblem" |
|
:key="item.id" |
|
:label="item.dictLabel" |
|
:value="item.dictValue" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item label="涉及警种" prop="policeType"> |
|
<el-select |
|
v-model="form.policeType" |
|
clearable |
|
style="width: 280px" |
|
> |
|
<el-option |
|
v-for="item in dict.policeType" |
|
:key="item.id" |
|
:label="item.dictLabel" |
|
:value="item.dictValue" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<div class="flex center mb-12"> |
|
<el-button |
|
@click="handleAddProblem()" |
|
plain |
|
type="primary" |
|
size="small" |
|
> |
|
<template #icon> |
|
<icon name="el-icon-Plus" /> |
|
</template> |
|
添加问题 |
|
</el-button> |
|
</div> |
|
<el-form-item |
|
label="问题类型" |
|
prop="" |
|
v-for="(item, index) in form.problems" |
|
:key="index" |
|
> |
|
<div class="flex v-center"> |
|
<problem-type-select v-model="item.threeLevelCode" /> |
|
<el-button |
|
plain |
|
type="danger" |
|
size="small" |
|
class="ml-20" |
|
@click="handleRemoveProblem(index)" |
|
> |
|
<template #icon> |
|
<icon name="el-icon-Delete" /> |
|
</template> |
|
删除问题 |
|
</el-button> |
|
</div> |
|
</el-form-item> |
|
|
|
<el-form-item |
|
label="办理时限" |
|
prop="timeLimit" |
|
:rules="{ |
|
required: true, |
|
message: '请选择办理时限', |
|
}" |
|
> |
|
<time-limit-select |
|
v-model="form.timeLimit" |
|
v-model:maxSignDuration="form.maxSignDuration" |
|
v-model:maxHandleDuration="form.maxHandleDuration" |
|
v-model:maxExtensionDuration="form.maxExtensionDuration" |
|
/> |
|
</el-form-item> |
|
<el-form-item |
|
label="下发流程" |
|
prop="distributionFlow" |
|
:rules="{ |
|
required: true, |
|
message: '请选择下发流程', |
|
}" |
|
> |
|
<el-radio-group |
|
v-model="form.distributionFlow" |
|
class="block" |
|
> |
|
<el-radio |
|
v-for="item in dict.distributionFlow" |
|
:key="item.dictCode" |
|
:value="item.dictValue" |
|
>{{ item.dictLabel }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
<el-form-item |
|
label="审核流程" |
|
prop="approvalFlow" |
|
:rules="{ |
|
required: true, |
|
message: '请选择审核流程', |
|
}" |
|
> |
|
<el-radio-group v-model="form.approvalFlow"> |
|
<el-radio |
|
v-for="item in dict.approvalFlow" |
|
:key="item.dictCode" |
|
:value="item.dictValue" |
|
>{{ item.dictLabel }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
</template> |
|
<template v-if="form.modelDataType === '2'"> |
|
<el-form-item |
|
label="回复方式" |
|
:rules="{ |
|
required: true, |
|
message: '请选择回复方式', |
|
}" |
|
> |
|
<el-switch |
|
v-model="form.requestReply" |
|
inline-prompt |
|
active-text="必须回复" |
|
inactive-text="消息确认" |
|
:active-value="true" |
|
:inactive-value="false" |
|
/> |
|
</el-form-item> |
|
<el-form-item |
|
label="时限设置" |
|
prop="replyLimit" |
|
:rules="{ |
|
required: true, |
|
message: '请选择时限设置', |
|
}" |
|
> |
|
<div class="flex gap"> |
|
<el-input |
|
style="width: 100px" |
|
type="number" |
|
v-model="form.replyLimit" |
|
:min="1" |
|
/><span>工作日</span> |
|
</div> |
|
</el-form-item> |
|
</template> |
|
<template |
|
v-if=" |
|
(form.modelType === '1' && |
|
form.modelDataType === '1' && |
|
form.distributionMethod === |
|
DistributionMethod.DIRECTLY_DISTRIBUTE) || |
|
form.modelDataType === '2' |
|
" |
|
> |
|
<el-form-item |
|
label="办理单位类型" |
|
prop="handleDepartType" |
|
:rules="{ |
|
required: true, |
|
message: '请选择办理单位类型', |
|
}" |
|
> |
|
<div> |
|
<el-radio-group |
|
v-model="form.handleDepartType" |
|
class="block" |
|
style="width: 270px" |
|
> |
|
<el-radio value="1">问题涉及单位</el-radio> |
|
<el-radio value="2">指定单位</el-radio> |
|
</el-radio-group> |
|
<div class="tips"> |
|
<span class="text-danger mr-8">说明</span> |
|
<span style="line-height: 1.2" |
|
>选择问题涉及单位,直接将通知发送至该问题的涉及单位,选择指定单位,则将通知发送至指定单位。</span |
|
> |
|
</div> |
|
</div> |
|
</el-form-item> |
|
<el-form-item |
|
label="指定单位" |
|
prop="handleDepartId" |
|
v-if="form.handleDepartType === '2'" |
|
:rules="{ |
|
required: true, |
|
message: '请选择指定单位', |
|
}" |
|
> |
|
<div class="flex gap"> |
|
<div style="width: 280px"> |
|
<depart-tree-select v-model="form.handleDepartId" /> |
|
</div> |
|
<div class="tips mt-10"> |
|
<p>指定具体办理单位 指将问题分派给哪个单位办理。</p> |
|
</div> |
|
</div> |
|
</el-form-item> |
|
</template> |
|
</el-form> |
|
<footer class="flex end"> |
|
<el-button @click="show = false" size="large">取消</el-button> |
|
<el-button type="primary" size="large" @click="handleSubmit">{{ |
|
mode === "add" ? "添加模型" : "确认" |
|
}}</el-button> |
|
</footer> |
|
</el-dialog> |
|
|
|
<el-dialog |
|
title="模型详情" |
|
v-model="detailShow" |
|
top="5vh" |
|
width="1100" |
|
style="margin-bottom: 2vh" |
|
> |
|
<header class="model-info-header" style=""> |
|
<el-row :gutter="40"> |
|
<el-col :span="2"> |
|
<div |
|
class="model-icon" |
|
:style="{ background: activeModel.iconColor }" |
|
> |
|
<icon :name="activeModel.icon" :size="80" /> |
|
</div> |
|
</el-col> |
|
<el-col :span="21"> |
|
<h1 style="color: #333; margin-top: 0" class="mb-10"> |
|
{{ activeModel.modelName }} |
|
</h1> |
|
<p>{{ activeModel.remarks }}</p> |
|
</el-col> |
|
</el-row> |
|
</header> |
|
<h4 style="margin: 10px 0" class="text-primary">模型信息</h4> |
|
<div class="row"> |
|
<div class="col col-6"> |
|
<label>建模方式</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.modelingMethod, |
|
activeModel.modelingMethod |
|
) |
|
}}</span> |
|
</div> |
|
<div class="col col-6"> |
|
<label>模型分类</label> |
|
<span>{{ |
|
getDictLable(dict.modelType, activeModel.modelType) |
|
}}</span> |
|
</div> |
|
<div class="col col-6"> |
|
<label>最近活跃时间</label> |
|
<span>{{ activeModel.updateTime }}</span> |
|
</div> |
|
<div class="col col-6"> |
|
<label>创建单位</label> |
|
<span>{{ activeModel.createDepartName || "/" }}</span> |
|
</div> |
|
<div class="col col-6"> |
|
<label>预警类型</label> |
|
<span>{{ |
|
form.modelDataType === "1" |
|
? form.modelType === "1" |
|
? "预警问题" |
|
: "预警处置" |
|
: "提醒通知" |
|
}}</span> |
|
</div> |
|
<div class="col col-6"> |
|
<label>分发方式</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.distributionMethod, |
|
activeModel.distributionMethod |
|
) |
|
}}</span> |
|
</div> |
|
</div> |
|
<div v-if="activeModel.distributionCycle"> |
|
<el-divider /> |
|
<div class="row"> |
|
<div class="col col-6"> |
|
<label>分发周期</label> |
|
<span> |
|
<span>{{ |
|
getDictLable( |
|
dict.distributionCycle, |
|
activeModel.distributionCycle |
|
) |
|
}}</span> |
|
<span class="ml-20">{{ |
|
activeModel.distributionCycleTime |
|
}}</span> |
|
</span> |
|
</div> |
|
<div class="col col-6" v-if="activeModel.timeLimit"> |
|
<label>办理时限</label> |
|
<span>{{ |
|
getDictLable(dict.timeLimit, activeModel.timeLimit) |
|
}}</span> |
|
</div> |
|
<div class="col col-6" v-if="activeModel.distributionFlow"> |
|
<label>下发流程</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.distributionFlow, |
|
activeModel.distributionFlow |
|
) |
|
}}</span> |
|
</div> |
|
<div class="col col-6" v-if="activeModel.approvalFlow"> |
|
<label>审核流程</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.approvalFlow, |
|
activeModel.approvalFlow |
|
) |
|
}}</span> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col col-6" v-if="activeModel.clueTableName"> |
|
<label>模型结果表</label> |
|
<span>{{ activeModel.clueTableName }}</span> |
|
</div> |
|
<div class="col col-6" v-if="activeModel.clueTimeFieldName"> |
|
<label>同步时间字段名</label> |
|
<span>{{ activeModel.clueTimeFieldName }}</span> |
|
</div> |
|
<div class="col col-6" v-if="activeModel.clueUniqueFieldName"> |
|
<label>同步唯一字段名</label> |
|
<span>{{ activeModel.clueUniqueFieldName }}</span> |
|
</div> |
|
</div> |
|
|
|
<el-divider /> |
|
<div class="flex end mb-20"> |
|
<el-button type="primary" plain @click="goClue">{{ |
|
activeModel.classId === GRJDBLFX_CLASS_ID |
|
? "查看风险问题" |
|
: "查看线索数据" |
|
}}</el-button> |
|
<!-- <el-button |
|
type="primary" |
|
plain |
|
@click="handleDetailConfigShow" |
|
> |
|
<template #icon> |
|
<icon name="el-icon-Edit" /> |
|
</template> |
|
线索详细信息配置</el-button |
|
> --> |
|
</div> |
|
<div class="mb-10"> |
|
<h4 style="margin: 10px 0" class="text-primary">预警记录</h4> |
|
<div style="min-height: 200px"> |
|
<div class="table-container"> |
|
<el-table :data="tableData" size="small"> |
|
<template |
|
v-if="activeModel.classId !== GRJDBLFX_CLASS_ID" |
|
> |
|
<el-table-column |
|
label="同步时间" |
|
prop="createTime" |
|
/> |
|
<el-table-column |
|
label="预警条数" |
|
prop="size" |
|
align="center" |
|
/> |
|
<el-table-column label="分发状态" align="center"> |
|
<template #default="{ row }"> |
|
<el-tag |
|
type="success" |
|
v-if="row.state === 'success'" |
|
>成功</el-tag |
|
> |
|
<el-tooltip |
|
effect="dark" |
|
:content="row.errMsg" |
|
placement="top-start" |
|
v-else |
|
> |
|
<el-tag type="danger">失败</el-tag> |
|
</el-tooltip> |
|
</template> |
|
</el-table-column> |
|
</template> |
|
<template v-else> |
|
<el-table-column |
|
label="开始时间" |
|
prop="startTime" |
|
/> |
|
<el-table-column label="结束时间" prop="endTime" /> |
|
<el-table-column |
|
label="新增条数" |
|
prop="insertSize" |
|
align="center" |
|
/> |
|
<el-table-column |
|
label="更新条数" |
|
prop="updateSize" |
|
align="center" |
|
/> |
|
<el-table-column label="状态" align="center"> |
|
<template #default="{ row }"> |
|
<el-tag |
|
type="success" |
|
v-if="row.state === 1" |
|
>成功</el-tag |
|
> |
|
<el-tag |
|
type="primary" |
|
v-if="row.state === 0" |
|
>进行中</el-tag |
|
> |
|
<el-tooltip |
|
effect="dark" |
|
:content="row.errMsg" |
|
placement="top-start" |
|
v-if="row.state === -1" |
|
> |
|
<el-tag type="danger">失败</el-tag> |
|
</el-tooltip> |
|
</template> |
|
</el-table-column> |
|
</template> |
|
</el-table> |
|
</div> |
|
</div> |
|
</div> |
|
<footer class="flex end"> |
|
<el-button @click="handleEdit" type="primary" plain size="large" |
|
>编辑模型</el-button |
|
> |
|
<el-button type="danger" plain @click="handleDel" size="large" |
|
>删除模型</el-button |
|
> |
|
</footer> |
|
</el-dialog> |
|
</template> |
|
<script setup> |
|
import { |
|
DistributionMethod, |
|
DistributionCycle, |
|
ModelDataType, |
|
} from "@/enums/dictEnums"; |
|
import { WEEKS } from "@/enums/appEnums"; |
|
import { MENU_ROOT_ID } from "@/enums/appEnums"; |
|
import { listModelClass } from "@/api/sensitivePerception/modelClass"; |
|
import { listRiskScoreRuleTreeOld } from "@/api/sensitivePerception/riskScoreRule"; |
|
import { |
|
addModel, |
|
updateModel, |
|
delModel, |
|
listModel, |
|
listClueMappingData, |
|
} from "@/api/sensitivePerception/model"; |
|
import { listModelClue } from "@/api/sensitivePerception/modelClue"; |
|
import { listTopModelClueRecords } from "@/api/sensitivePerception/modelClue"; |
|
import useCatchStore from "@/stores/modules/catch"; |
|
import { getDictLable } from "@/utils/util"; |
|
import feedback from "@/utils/feedback"; |
|
|
|
const catchStore = useCatchStore(); |
|
const dict = catchStore.getDicts([ |
|
"distributionMethod", |
|
"distributionCycle", |
|
"distributionFlow", |
|
"timeLimit", |
|
"approvalFlow", |
|
"modelingMethod", |
|
"modelDataType", |
|
"businessType", |
|
"suspectProblem", |
|
"policeType", |
|
"modelType", |
|
"departMappingSource", |
|
]); |
|
|
|
// 个人极端暴力风险 |
|
const GRJDBLFX_CLASS_ID = 6; |
|
|
|
const router = useRouter(); |
|
|
|
const query = ref({ |
|
size: 12, |
|
current: 1, |
|
}); |
|
const total = ref(0); |
|
const list = ref([]); |
|
const classes = ref([]); |
|
|
|
function getList() { |
|
listModel(query.value).then((data) => { |
|
list.value = data.records; |
|
total.value = data.total; |
|
}); |
|
} |
|
|
|
function reset() { |
|
query.value = { |
|
size: 12, |
|
current: 1, |
|
}; |
|
getList(); |
|
} |
|
|
|
const treeOptions = ref([]); |
|
|
|
onMounted(() => { |
|
getList(); |
|
listModelClass().then((data) => { |
|
classes.value = data; |
|
}); |
|
listRiskScoreRuleTreeOld().then((data) => { |
|
treeOptions.value = data; |
|
}); |
|
}); |
|
|
|
function handleChangeClass(id) { |
|
query.value.classId = id; |
|
} |
|
|
|
watch( |
|
() => query.value.classId, |
|
() => { |
|
query.value.current = 1; |
|
getList(); |
|
} |
|
); |
|
|
|
const show = ref(false); |
|
const mode = ref("add"); |
|
const form = ref({ |
|
distributionMethod: "1", |
|
problems: [], |
|
requestReply: true, |
|
}); |
|
|
|
watch(mode, (val) => { |
|
if (val === "add") { |
|
initForm(); |
|
} |
|
}); |
|
|
|
function initForm() { |
|
form.value = { |
|
distributionMethod: "1", |
|
problems: [], |
|
requestReply: true, |
|
}; |
|
} |
|
const formRef = ref(null); |
|
|
|
const clueMappingData = ref([]); |
|
async function handleAdd() { |
|
show.value = true; |
|
mode.value = "add"; |
|
clueMappingData.value = await listClueMappingData(); |
|
} |
|
|
|
function handleEdit() { |
|
show.value = true; |
|
mode.value = "edit"; |
|
form.value = { ...activeModel.value }; |
|
if (activeModel.value.involveProblem) { |
|
form.value.involveProblem = activeModel.value.involveProblem.split(","); |
|
} else { |
|
form.value.involveProblem = []; |
|
} |
|
} |
|
|
|
function handleAddProblem() { |
|
form.value.problems.push({}); |
|
} |
|
|
|
function handleRemoveProblem(index) { |
|
form.value.problems.splice(index, 1); |
|
} |
|
|
|
async function handleSubmit() { |
|
if (form.value.modelingMethod === "2") { |
|
if (!modelClueTargetColumns.value[1].columnName |
|
) { |
|
feedback.msgWarning("请选择结果字段映射【红色为必填】"); |
|
return; |
|
} |
|
form.value.modelGeneration = { |
|
involveDepartName: modelClueTargetColumns.value[0].columnName, |
|
involveDepartId: modelClueTargetColumns.value[1].columnName, |
|
involvePoliceName: modelClueTargetColumns.value[2].columnName, |
|
involvePoliceEmpNo: modelClueTargetColumns.value[3].columnName, |
|
happenTime: modelClueTargetColumns.value[4].columnName, |
|
}; |
|
} |
|
await formRef.value.validate(); |
|
if (mode.value === "add") { |
|
await addModel(form.value); |
|
} else { |
|
activeModel.value = await updateModel(form.value); |
|
} |
|
getList(); |
|
show.value = false; |
|
initForm(); |
|
feedback.msgSuccess("操作成功"); |
|
} |
|
|
|
async function handleDel() { |
|
await feedback.confirm("确定删除该模型?"); |
|
await delModel(activeModel.value.id); |
|
feedback.msgSuccess("操作成功"); |
|
getList(); |
|
detailShow.value = false; |
|
} |
|
|
|
const detailShow = ref(false); |
|
const activeModel = ref({}); |
|
const tableData = ref([]); |
|
|
|
async function openDetail(item) { |
|
activeModel.value = item; |
|
tableData.value = await listTopModelClueRecords(item.id); |
|
detailShow.value = true; |
|
} |
|
|
|
const detailConfigShow = ref(false); |
|
const modelClueData = ref({}); |
|
async function handleDetailConfigShow() { |
|
const data = await listModelClue({ |
|
modelIds: [activeModel.value.id], |
|
current: 1, |
|
size: 1, |
|
}); |
|
if (data.records.length && data.records[0].data) { |
|
} else { |
|
modelClueData.value = JSON.parse(data.records[0].data); |
|
} |
|
detailConfigShow.value = true; |
|
} |
|
|
|
function goClue() { |
|
if (activeModel.value.classId === GRJDBLFX_CLASS_ID) { |
|
router.push({ |
|
path: `/sensitivePerception/riskClue`, |
|
query: { |
|
riskScoreRuleId: activeModel.value.id, |
|
}, |
|
}); |
|
} else { |
|
router.push({ |
|
path: `/sensitivePerception/modelClue`, |
|
query: { |
|
modelId: activeModel.value.id, |
|
}, |
|
}); |
|
} |
|
} |
|
|
|
const modelClueColumns = [ |
|
{ |
|
fieldName: "involvo_depart_name", |
|
fieldType: "varchar", |
|
fieldDesc: "涉及单位名称" |
|
}, |
|
{ |
|
fieldName: "involvo_depart_id", |
|
fieldType: "varchar", |
|
fieldDesc: "涉及单位ID", |
|
required: true, |
|
}, |
|
{ |
|
fieldName: "involvo_police_name", |
|
fieldType: "varchar", |
|
fieldDesc: "涉及人员姓名", |
|
}, |
|
{ |
|
fieldName: "involvo_police_emp_no", |
|
fieldType: "varchar", |
|
fieldDesc: "涉及人员警号", |
|
}, |
|
{ |
|
fieldName: "happen_time", |
|
fieldType: "varchar", |
|
fieldDesc: "发生时间", |
|
}, |
|
]; |
|
|
|
function handleChangeColumn(val, row) { |
|
const item = fields.value.find((item) => item.columnName === val); |
|
|
|
row.dataType = item.dataType; |
|
row.columnComment = item.columnComment; |
|
} |
|
const modelClueTargetColumns = ref([{}, {}, {}, {}, {}]); |
|
|
|
const fields = ref([]); |
|
function handleSelectClueTableName(val) { |
|
if (val) { |
|
fields.value = clueMappingData.value.filter( |
|
(item) => item.tableName === val |
|
)[0].fields; |
|
} |
|
} |
|
</script> |
|
<style lang="scss" scoped> |
|
.menu { |
|
> div { |
|
height: 47px; |
|
line-height: 47px; |
|
padding-left: 16px; |
|
white-space: nowrap; |
|
overflow: hidden; |
|
text-overflow: ellipsis; |
|
&:hover, |
|
&[active="true"] { |
|
background: #e1e5ff; |
|
cursor: pointer; |
|
} |
|
} |
|
} |
|
.model-card { |
|
background: #f6f7ff; |
|
border: 1px solid #e1e5ff; |
|
border-radius: 4px; |
|
padding: 18px; |
|
&:hover { |
|
border-color: var(--primary-color); |
|
cursor: pointer; |
|
} |
|
|
|
.col { |
|
--label-width: 78px; |
|
} |
|
} |
|
.model-icon { |
|
width: 80px; |
|
border-radius: 8px; |
|
} |
|
.model-info-header { |
|
background: #f9faff; |
|
box-shadow: 0px 2px 4px 0px rgba(133, 150, 248, 0.47); |
|
padding: 28px; |
|
} |
|
.field-table-title { |
|
font-weight: 700; |
|
color: var(--primary-color); |
|
margin-bottom: 8px; |
|
font-size: 15px; |
|
} |
|
.field-arrow { |
|
height: 32px; |
|
line-height: 32px; |
|
width: 100%; |
|
} |
|
.field-table_target { |
|
:deep() { |
|
.el-table--small .el-table__cell { |
|
padding: 2px 0; |
|
} |
|
} |
|
} |
|
</style> |