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

344 lines
9.9 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="80px"
>
<el-form-item label="标题" prop="title">
<el-input
v-model="queryParams.title"
placeholder="请输入标题"
clearable
@keyup.enter="handleQuery"
class="!w-160px"
/>
</el-form-item>
<el-form-item label="分类" prop="category">
<el-select
v-model="queryParams.category"
placeholder="请选择"
clearable
class="!w-120px"
>
<el-option
v-for="dict in categoryOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="等级" prop="level">
<el-select
v-model="queryParams.level"
placeholder="请选择"
clearable
class="!w-100px"
>
<el-option
v-for="dict in levelOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择"
clearable
class="!w-100px"
>
<el-option
v-for="dict in statusOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="监区" prop="areaId">
<el-tree-select
v-model="queryParams.areaId"
:data="areaTreeList"
:props="{ label: 'name', value: 'id', children: 'children' }"
placeholder="请选择监区"
clearable
filterable
class="!w-180px"
:render-after-expand="false"
/>
</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:situation:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增狱情
</el-button>
<el-button
type="warning"
plain
@click="handleImport"
v-hasPermi="['prison:situation:import']"
>
<Icon icon="ep:upload" class="mr-5px" /> 导入
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['prison:situation: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"
>
<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="title" min-width="150" show-overflow-tooltip />
<el-table-column label="分类" align="center" prop="category" width="100">
<template #default="{ row }">
<dict-tag :type="DICT_TYPE.PRISON_SITUATION_CATEGORY" :value="row.category" />
</template>
</el-table-column>
<el-table-column label="等级" align="center" prop="level" width="90">
<template #default="{ row }">
<dict-tag :type="DICT_TYPE.PRISON_SITUATION_LEVEL" :value="row.level" />
</template>
</el-table-column>
<el-table-column label="来源" align="center" prop="source" width="100">
<template #default="{ row }">
<dict-tag :type="DICT_TYPE.PRISON_SITUATION_SOURCE" :value="row.source" />
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" width="100">
<template #default="{ row }">
<dict-tag :type="DICT_TYPE.PRISON_SITUATION_STATUS" :value="row.status" />
</template>
</el-table-column>
<el-table-column label="监区" align="center" prop="areaName" width="120" />
<el-table-column label="报告人" align="center" prop="reporter" width="100" />
<el-table-column label="发生时间" align="center" prop="occurTime" width="160">
<template #default="{ row }">
<span v-if="row.occurTime">{{ formatDateTime(row.occurTime) }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<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="180" 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:situation:update']"
>
<Icon icon="ep:edit" class="mr-5px" /> 修改
</el-button>
<el-button
link
type="danger"
@click="handleDelete(row.id)"
v-hasPermi="['prison:situation: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>
<!-- 表单弹窗添加/修改 -->
<SituationForm ref="formRef" @success="getList" />
<!-- 导入弹窗 -->
<ImportDialog
ref="importDialogRef"
:import-url="getImportUrl()"
template-url="/prison/situation/get-import-template"
template-name="狱情收集导入模板.xls"
title="导入狱情收集"
@success="getList"
/>
</template>
<script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { formatDateTime } from '@/utils/formatTime'
import download from '@/utils/download'
import { SituationApi, SituationPageReqVO } from '@/api/prison/situation'
import SituationForm from './SituationForm.vue'
import ImportDialog from '@/components/ImportDialog/index.vue'
defineOptions({ name: 'PrisonSituation' })
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<SituationPageReqVO>({
pageNo: 1,
pageSize: 10,
title: undefined,
category: undefined,
level: undefined,
source: undefined,
status: undefined,
areaId: undefined,
cellId: undefined,
reporter: undefined
})
const queryFormRef = ref()
// 字典数据
const categoryOptions = getIntDictOptions(DICT_TYPE.PRISON_SITUATION_CATEGORY)
const levelOptions = getIntDictOptions(DICT_TYPE.PRISON_SITUATION_LEVEL)
const sourceOptions = getIntDictOptions(DICT_TYPE.PRISON_SITUATION_SOURCE)
const statusOptions = getIntDictOptions(DICT_TYPE.PRISON_SITUATION_STATUS)
// 监区选项
const areaOptions = ref<{ id: number; name: string }[]>([])
// 监区树形列表
const areaTreeList = ref<any[]>([])
/** 获取监区树形列表 */
const loadAreas = async () => {
areaTreeList.value = await SituationApi.AreaApi.getAreaTree()
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await SituationApi.getSituationPage(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 SituationApi.deleteSituation(id)
message.success(t('common.delSuccess'))
getList()
} catch {}
}
/** 批量删除 */
const handleBatchDelete = async () => {
if (selectedIds.value.length === 0) {
message.warning('请选择要删除的数据')
return
}
try {
await message.delConfirm()
await SituationApi.deleteSituationList(selectedIds.value)
message.success(t('common.delSuccess'))
getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const data = await SituationApi.exportSituation(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/situation/import'
}
/** 初始化 */
onMounted(() => {
getList()
loadAreas()
})
</script>