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.
756 lines
28 KiB
756 lines
28 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" |
|
> |
|
{{ item.name }} |
|
</div> |
|
</div> |
|
</el-col> |
|
<el-col :span="20"> |
|
<el-form :label-width="140"> |
|
<el-row> |
|
<el-col :span="8"> |
|
<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="18"> |
|
<el-col :span="8" v-for="item in list" class="mb-18"> |
|
<div class="model-card" @click="openDetail(item)"> |
|
<div class="flex v-center"> |
|
<div class="model-card-icon"> |
|
<icon |
|
:name="item.icon" |
|
:size="76" |
|
v-if="item.icon" |
|
/> |
|
</div> |
|
<div |
|
class="model-card-content" |
|
style="width: calc(100% - 76px)" |
|
> |
|
<el-tooltip :content="item.remarks"> |
|
<div> |
|
<div class="row"> |
|
<div class="col"> |
|
<label>模型名称</label> |
|
<span>{{ |
|
item.modelName |
|
}}</span> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col"> |
|
<label>创建单位</label> |
|
<span>{{ |
|
item.createDepartName |
|
}}</span> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col col-12"> |
|
<label>分发方式</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.distributionMethod, |
|
item.distributionMethod |
|
) |
|
}}</span> |
|
</div> |
|
</div> |
|
<div class="col"> |
|
<label>最近活跃时间</label> |
|
<span>{{ |
|
item.updateTime |
|
}}</span> |
|
</div> |
|
</div> |
|
</el-tooltip> |
|
</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" |
|
:current-page="query.current" |
|
:page-sizes="[9, 18, 36]" |
|
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="120" ref="formRef" :model="form"> |
|
<el-form-item |
|
label="模型类型" |
|
prop="classId" |
|
:rules="{ |
|
required: true, |
|
message: '请选择模型类型', |
|
}" |
|
> |
|
<el-select v-model="form.classId" style="width: 340px"> |
|
<el-option |
|
v-for="item in classes" |
|
:key="item.id" |
|
:label="item.name" |
|
:value="item.id" |
|
/> |
|
</el-select> |
|
</el-form-item> |
|
<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="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> |
|
<el-form-item |
|
label="模型图标" |
|
prop="icon" |
|
:rules="{ |
|
required: true, |
|
message: '请选择模型图标', |
|
}" |
|
> |
|
<model-icon-picker v-model="form.icon" /> |
|
</el-form-item> |
|
<el-form-item |
|
label="数据类型" |
|
prop="modelDataType" |
|
:rules="{ |
|
required: true, |
|
message: '请选择数据类型', |
|
}" |
|
> |
|
<el-radio-group v-model="form.modelDataType" class="block"> |
|
<el-radio |
|
v-for="item in dict.modelDataType" |
|
:key="item.dictCode" |
|
:value="item.dictValue" |
|
>{{ item.dictLabel |
|
}}{{ item.remark ? `(${item.remark})` : "" }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
<el-form-item |
|
label="分发方式" |
|
prop="distributionMethod" |
|
:rules="{ |
|
required: true, |
|
message: '请选择分发方式', |
|
}" |
|
v-if="form.modelDataType === ModelDataType.NEGATIVE" |
|
> |
|
<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 |
|
}}{{ item.remark ? `(${item.remark})` : "" }}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
|
|
<template |
|
v-if=" |
|
form.modelDataType === ModelDataType.NEGATIVE && |
|
form.distributionMethod === |
|
DistributionMethod.DIRECTLY_DISTRIBUTE |
|
" |
|
> |
|
<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 |
|
}}{{ |
|
item.remark ? `(${item.remark})` : "" |
|
}}</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> |
|
<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="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 |
|
}}{{ |
|
item.remark ? `(${item.remark})` : "" |
|
}}</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 |
|
}}{{ |
|
item.remark ? `(${item.remark})` : "" |
|
}}</el-radio |
|
> |
|
</el-radio-group> |
|
</el-form-item> |
|
</template> |
|
<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="提示"> |
|
<div style="line-height: 1.4"> |
|
预警数据将以任务形式分批下发至相关单位处理。每次下发的预警数据都会在“任务分发”模块中生成一条记录。任务名称将按照“模型名称_下发时间”的格式命名,例如:“取保候审期间未按要求传讯犯罪嫌疑人_20240919” |
|
</div> |
|
</el-form-item> |
|
</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="70vw"> |
|
<h4 style="margin: 10px 0" class="text-primary">模型信息</h4> |
|
<el-row> |
|
<el-col :span="4"> |
|
<div class="mb-10">模型图标</div> |
|
<div> |
|
<icon :name="activeModel.icon" :size="80" /> |
|
</div> |
|
</el-col> |
|
<el-col :span="20"> |
|
<div class="row"> |
|
<div class="col col-24"> |
|
<label>模型名称</label> |
|
<span>{{ activeModel.modelName }}</span> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col col-8"> |
|
<label>建模方式</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.modelingMethod, |
|
activeModel.modelingMethod |
|
) |
|
}}</span> |
|
</div> |
|
<div class="col col-8"> |
|
<label>数据类型</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.modelDataType, |
|
activeModel.modelDataType |
|
) |
|
}}</span> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col col-8"> |
|
<label>分发方式</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.distributionMethod, |
|
activeModel.distributionMethod |
|
) |
|
}}</span> |
|
</div> |
|
<div class="col col-8"> |
|
<label>分发周期</label> |
|
<span> |
|
<span>{{ |
|
getDictLable( |
|
dict.distributionCycle, |
|
activeModel.distributionCycle |
|
) |
|
}}</span> |
|
<span class="ml-20">{{ |
|
activeModel.distributionCycleTime |
|
}}</span> |
|
</span> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col col-8"> |
|
<label>办理时限</label> |
|
<span>{{ |
|
getDictLable(dict.timeLimit, activeModel.timeLimit) |
|
}}</span> |
|
</div> |
|
<div class="col col-8"> |
|
<label>下发流程</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.distributionFlow, |
|
activeModel.distributionFlow |
|
) |
|
}}</span> |
|
</div> |
|
<div class="col col-8"> |
|
<label>审核流程</label> |
|
<span>{{ |
|
getDictLable( |
|
dict.approvalFlow, |
|
activeModel.approvalFlow |
|
) |
|
}}</span> |
|
</div> |
|
</div> |
|
<div class="row"> |
|
<div class="col col-8"> |
|
<label>最近活跃时间</label> |
|
<span>{{ activeModel.updateTime }}</span> |
|
</div> |
|
<div class="col col-8"> |
|
<label>创建单位</label> |
|
<span>{{ activeModel.createDepartName }}</span> |
|
</div> |
|
</div> |
|
<div class="row mb-20"> |
|
<div class="col col-24"> |
|
<label>模型描述</label> |
|
<span>{{ activeModel.remarks }}</span> |
|
</div> |
|
</div> |
|
<div class="flex end mb-20"> |
|
<el-button |
|
type="primary" |
|
plain |
|
@click=" |
|
router.push({ |
|
path: `/sensitivePerception/modelClue`, |
|
query: { |
|
modelId: activeModel.id, |
|
}, |
|
}) |
|
" |
|
>查看线索数据</el-button |
|
> |
|
<el-button type="primary" plain @click="handleDetailConfigShow"> |
|
<template #icon> |
|
<icon name="el-icon-Edit" /> |
|
</template> |
|
线索详细信息配置</el-button |
|
> |
|
</div> |
|
</el-col> |
|
</el-row> |
|
<div class="mb-10"> |
|
<h4 style="margin: 10px 0" class="text-primary">预警记录</h4> |
|
<div style="min-height: 300px"> |
|
<div class="table-container"> |
|
<el-table :data="tableData" size="small"> |
|
<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> |
|
</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> |
|
|
|
<el-dialog title="线索详细信息配置" v-model="detailConfigShow" width="800px"> |
|
|
|
</el-dialog> |
|
</template> |
|
<script setup> |
|
import { |
|
DistributionMethod, |
|
DistributionCycle, |
|
ModelDataType, |
|
} from "@/enums/dictEnums"; |
|
import { WEEKS } from "@/enums/appEnums"; |
|
import { listModelClass } from "@/api/sensitivePerception/modelClass"; |
|
import { |
|
addModel, |
|
updateModel, |
|
delModel, |
|
listModel, |
|
} 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", |
|
]); |
|
|
|
const router = useRouter(); |
|
|
|
const query = ref({ |
|
size: 9, |
|
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: 9, |
|
current: 1, |
|
}; |
|
getList(); |
|
} |
|
|
|
onMounted(() => { |
|
getList(); |
|
listModelClass().then((data) => { |
|
classes.value = data; |
|
}); |
|
}); |
|
|
|
function handleChangeClass(id) { |
|
query.value.classId = id; |
|
getList(); |
|
} |
|
|
|
const show = ref(false); |
|
const mode = ref("add"); |
|
const form = ref({ |
|
distributionMethod: "1", |
|
}); |
|
|
|
watch(mode, (val) => { |
|
if (val === "add") { |
|
initForm(); |
|
} |
|
}); |
|
|
|
function initForm() { |
|
form.value = { distributionMethod: "1" }; |
|
} |
|
const formRef = ref(null); |
|
|
|
function handleAdd() { |
|
show.value = true; |
|
mode.value = "add"; |
|
} |
|
|
|
function handleEdit() { |
|
show.value = true; |
|
mode.value = "edit"; |
|
form.value = { ...activeModel.value }; |
|
} |
|
|
|
async function handleSubmit() { |
|
await formRef.value.validate(); |
|
if (mode.value === "add") { |
|
await addModel(form.value); |
|
} else { |
|
activeModel.value = await updateModel(form.value); |
|
} |
|
getList(); |
|
initForm(); |
|
show.value = false; |
|
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) { |
|
console.log(data.records) |
|
} else { |
|
modelClueData.value = JSON.parse(data.records[0].data) |
|
} |
|
detailConfigShow.value = true |
|
} |
|
</script> |
|
<style lang="scss" scoped> |
|
.menu { |
|
> div { |
|
height: 47px; |
|
line-height: 47px; |
|
padding: 0 36px; |
|
&: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; |
|
} |
|
.model-card-icon { |
|
width: 76px; |
|
} |
|
.col { |
|
--label-width: 78px; |
|
} |
|
} |
|
</style> |