tangweijie e8d78a1aea feat: 新增AI监控仪表盘前端页面和功能
- 新增AI监控仪表盘入口页面(DashEntry.vue)
- 新增AI监控相关API(ai-dash-entry)
- 新增导入对话框组件(ImportDialog)
- 各模块页面新增导入按钮和功能
- 优化国际化配置和路由权限

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-21 00:19:30 +08:00

326 lines
9.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="90px"
>
<el-form-item label="罪犯编号" prop="prisonerCode">
<el-input
v-model="queryParams.prisonerCode"
placeholder="请输入罪犯编号"
clearable
@keyup.enter="handleQuery"
class="!w-140px"
/>
</el-form-item>
<el-form-item label="罪犯姓名" prop="prisonerName">
<el-input
v-model="queryParams.prisonerName"
placeholder="请输入罪犯姓名"
clearable
@keyup.enter="handleQuery"
class="!w-140px"
/>
</el-form-item>
<el-form-item label="评估类型" prop="assessmentType">
<el-select
v-model="queryParams.assessmentType"
placeholder="请选择"
clearable
class="!w-120px"
>
<el-option
v-for="dict in assessmentTypeOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="风险等级" prop="riskLevel">
<el-select
v-model="queryParams.riskLevel"
placeholder="请选择"
clearable
class="!w-100px"
>
<el-option
v-for="dict in riskLevelOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="评估人" prop="assessor">
<el-input
v-model="queryParams.assessor"
placeholder="请输入评估人"
clearable
@keyup.enter="handleQuery"
class="!w-120px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['prison:risk:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增评估
</el-button>
<el-button
type="warning"
plain
@click="handleImport"
v-hasPermi="['prison:risk:import']"
>
<Icon icon="ep:upload" class="mr-5px" /> 导入
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['prison:risk:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
:scroll-x="true"
style="width: 100%; min-width: 1200px"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="编号" align="center" prop="id" width="80" />
<el-table-column label="罪犯编号" align="center" prop="prisonerCode" width="100" />
<el-table-column label="罪犯姓名" align="center" prop="prisonerName" width="100" />
<el-table-column label="评估类型" align="center" prop="assessmentType" width="120">
<template #default="{ row }">
<dict-tag :type="DICT_TYPE.PRISON_RISK_ASSESSMENT_TYPE" :value="row.assessmentType" />
</template>
</el-table-column>
<el-table-column label="评估日期" align="center" prop="assessmentDate" width="120">
<template #default="{ row }">
<span v-if="row.assessmentDate">{{ formatDate(row.assessmentDate) }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="综合得分" align="center" prop="overallScore" width="100">
<template #default="{ row }">
<span :class="getScoreClass(row.overallScore)">{{ row.overallScore ?? '-' }}</span>
</template>
</el-table-column>
<el-table-column label="风险等级" align="center" prop="riskLevel" width="100">
<template #default="{ row }">
<dict-tag :type="DICT_TYPE.PRISON_RISK_LEVEL" :value="row.riskLevel" />
</template>
</el-table-column>
<el-table-column label="评估人" align="center" prop="assessor" width="100" />
<el-table-column label="创建时间" align="center" prop="createTime" width="160">
<template #default="{ row }">
<span v-if="row.createTime">{{ formatDateTime(row.createTime) }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="200" fixed="right">
<template #default="{ row }">
<el-button
link
type="primary"
@click="openForm('view', row.id)"
>
<Icon icon="ep:view" class="mr-5px" /> 查看
</el-button>
<el-button
link
type="primary"
@click="openForm('update', row.id)"
v-hasPermi="['prison:risk:update']"
>
<Icon icon="ep:edit" class="mr-5px" /> 修改
</el-button>
<el-button
link
type="danger"
@click="handleDelete(row.id)"
v-hasPermi="['prison:risk:delete']"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<RiskForm ref="formRef" @success="getList" />
<!-- 导入弹窗 -->
<ImportDialog
ref="importDialogRef"
:import-url="getImportUrl()"
template-url="/prison/risk/get-import-template"
template-name="风险评估导入模板.xls"
title="导入风险评估"
@success="getList"
/>
</template>
<script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { formatDateTime, formatDate } from '@/utils/formatTime'
import download from '@/utils/download'
import { RiskApi, RiskPageReqVO } from '@/api/prison/risk'
import RiskForm from './RiskForm.vue'
import ImportDialog from '@/components/ImportDialog/index.vue'
defineOptions({ name: 'PrisonRisk' })
const message = useMessage()
const { t } = useI18n()
const loading = ref(false)
const exportLoading = ref(false)
const list = ref<any[]>([])
const total = ref(0)
const selectedIds = ref<number[]>([])
// 查询参数
const queryParams = reactive<RiskPageReqVO>({
pageNo: 1,
pageSize: 10,
prisonerCode: undefined,
prisonerName: undefined,
assessmentType: undefined,
riskLevel: undefined,
assessor: undefined,
assessmentDate: undefined
})
const queryFormRef = ref()
// 字典数据
const assessmentTypeOptions = getIntDictOptions(DICT_TYPE.PRISON_RISK_ASSESSMENT_TYPE)
const riskLevelOptions = getIntDictOptions(DICT_TYPE.PRISON_RISK_LEVEL)
/** 根据得分返回样式类名 */
const getScoreClass = (score: number | undefined) => {
if (score === undefined || score === null) return ''
if (score >= 80) return 'text-success'
if (score >= 60) return 'text-warning'
return 'text-danger'
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await RiskApi.getRiskPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 多选操作 */
const handleSelectionChange = (selection: any[]) => {
selectedIds.value = selection.map((item) => item.id)
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
await message.delConfirm()
await RiskApi.deleteRisk(id)
message.success(t('common.delSuccess'))
getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const data = await RiskApi.exportRisk(queryParams)
download.excel(data, '风险评估.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 导入操作 */
const importDialogRef = ref()
const handleImport = () => {
importDialogRef.value.open()
}
const getImportUrl = () => {
return import.meta.env.VITE_BASE_URL + (import.meta.env.VITE_API_URL || '/admin-api') + '/prison/risk/import'
}
/** 初始化 */
onMounted(() => {
getList()
})
</script>
<style scoped>
.text-success {
color: #67c23a;
font-weight: bold;
}
.text-warning {
color: #e6a23c;
font-weight: bold;
}
.text-danger {
color: #f56c6c;
font-weight: bold;
}
</style>