feat(prison): Enhance area and cell management with tree structure and improved forms
- Updated AreaApi to support search parameters in getAreaTree method. - Modified CellForm and Cell index views to use tree-select for area selection. - Added areaName to Cell and Prisoner interfaces for better data representation. - Refactored prisoner forms to remove subAreaId and streamline area selection. - Improved image path validation in utility functions. - Enhanced prisoner detail and list views to display area and cell names correctly. - Added loading functionality for area tree data in relevant components.
This commit is contained in:
parent
4be92f62bd
commit
1ebf700cf2
@ -72,8 +72,8 @@ export const AreaApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 查询监区树形结构
|
// 查询监区树形结构
|
||||||
getAreaTree: async () => {
|
getAreaTree: async (params?: { name?: string; type?: number; level?: number; status?: number }) => {
|
||||||
return await request.get({ url: `/prison/area/tree` })
|
return await request.get({ url: `/prison/area/tree`, params })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 查询父级监区列表(用于新增/编辑时选择)
|
// 查询父级监区列表(用于新增/编辑时选择)
|
||||||
@ -106,8 +106,8 @@ export const AreaApi = {
|
|||||||
return await request.download({ url: `/prison/area/export-excel`, params })
|
return await request.download({ url: `/prison/area/export-excel`, params })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 同步监区人数
|
// 同步监区当前人数
|
||||||
syncCurrentCount: async (id: number) => {
|
syncCurrentCount: async (areaId: number) => {
|
||||||
return await request.put({ url: `/prison/area/sync-count?id=` + id })
|
return await request.post({ url: `/prison/area/sync-current-count?areaId=` + areaId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5,6 +5,7 @@ import type { Dayjs } from 'dayjs';
|
|||||||
export interface Cell {
|
export interface Cell {
|
||||||
id: number; // 监室ID
|
id: number; // 监室ID
|
||||||
areaId?: number; // 所属监区ID
|
areaId?: number; // 所属监区ID
|
||||||
|
areaName?: string; // 所属监区名称
|
||||||
name?: string; // 监室名称
|
name?: string; // 监室名称
|
||||||
code?: string; // 监室编码
|
code?: string; // 监室编码
|
||||||
capacity: number; // 床位数量
|
capacity: number; // 床位数量
|
||||||
|
|||||||
@ -31,8 +31,6 @@ export interface PrisonerVO {
|
|||||||
riskLevelName?: string // 风险等级名称
|
riskLevelName?: string // 风险等级名称
|
||||||
prisonAreaId: number
|
prisonAreaId: number
|
||||||
prisonAreaName?: string // 监区名称
|
prisonAreaName?: string // 监区名称
|
||||||
subAreaId?: number // 分监区ID
|
|
||||||
subAreaName?: string // 分监区名称
|
|
||||||
prisonCellId: number
|
prisonCellId: number
|
||||||
prisonCellName?: string // 监室名称
|
prisonCellName?: string // 监室名称
|
||||||
status: number
|
status: number
|
||||||
@ -71,7 +69,6 @@ export interface PrisonerCreateVO {
|
|||||||
supervisionLevel: number
|
supervisionLevel: number
|
||||||
riskLevel: number
|
riskLevel: number
|
||||||
prisonAreaId: number
|
prisonAreaId: number
|
||||||
subAreaId?: number // 分监区ID
|
|
||||||
prisonCellId: number
|
prisonCellId: number
|
||||||
photo?: string // 照片URL
|
photo?: string // 照片URL
|
||||||
remark: string
|
remark: string
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
import { describe, it, expect } from 'vitest'
|
import { describe, it, expect } from 'vitest'
|
||||||
|
|
||||||
|
// Mock document for isElement test
|
||||||
|
const div = { tagName: 'DIV' }
|
||||||
|
global.document = { createElement: () => div }
|
||||||
|
|
||||||
import {
|
import {
|
||||||
is,
|
is,
|
||||||
isDef,
|
isDef,
|
||||||
@ -27,7 +32,7 @@ describe('is', () => {
|
|||||||
describe('is()', () => {
|
describe('is()', () => {
|
||||||
it('should return true for matching type', () => {
|
it('should return true for matching type', () => {
|
||||||
expect(is({}, 'Object')).toBe(true)
|
expect(is({}, 'Object')).toBe(true)
|
||||||
expect(is([], 'Object')).toBe(true)
|
expect(is([], 'Array')).toBe(true)
|
||||||
expect(is('test', 'String')).toBe(true)
|
expect(is('test', 'String')).toBe(true)
|
||||||
expect(is(123, 'Number')).toBe(true)
|
expect(is(123, 'Number')).toBe(true)
|
||||||
})
|
})
|
||||||
@ -263,7 +268,7 @@ describe('is', () => {
|
|||||||
expect(isImgPath('https://example.com/image.png')).toBe(true)
|
expect(isImgPath('https://example.com/image.png')).toBe(true)
|
||||||
expect(isImgPath('http://example.com/photo.jpg')).toBe(true)
|
expect(isImgPath('http://example.com/photo.jpg')).toBe(true)
|
||||||
expect(isImgPath('/path/to/image.gif')).toBe(true)
|
expect(isImgPath('/path/to/image.gif')).toBe(true)
|
||||||
expect(isImgPath('data:image/png;base64,abc123')).toBe(true)
|
expect(isImgPath('data:image/png;base64,iVBOR')).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return false for non-image paths', () => {
|
it('should return false for non-image paths', () => {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const toString = Object.prototype.toString
|
const toString = Object.prototype.toString
|
||||||
|
|
||||||
export const is = (val: unknown, type: string) => {
|
export const is = (val: unknown, type: string): boolean => {
|
||||||
return toString.call(val) === `[object ${type}]`
|
return toString.call(val) === `[object ${type}]`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ export const isNull = (val: unknown): val is null => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isNullAndUnDef = (val: unknown): val is null | undefined => {
|
export const isNullAndUnDef = (val: unknown): val is null | undefined => {
|
||||||
return isUnDef(val) && isNull(val)
|
return isUnDef(val) || isNull(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isNullOrUnDef = (val: unknown): val is null | undefined => {
|
export const isNullOrUnDef = (val: unknown): val is null | undefined => {
|
||||||
@ -86,7 +86,7 @@ export const isWindow = (val: any): val is Window => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isElement = (val: unknown): val is Element => {
|
export const isElement = (val: unknown): val is Element => {
|
||||||
return isObject(val) && !!val.tagName
|
return isObject(val) && typeof (val as any).tagName === 'string'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isMap = (val: unknown): val is Map<any, any> => {
|
export const isMap = (val: unknown): val is Map<any, any> => {
|
||||||
@ -110,7 +110,7 @@ export const isDark = (): boolean => {
|
|||||||
|
|
||||||
// 是否是图片链接
|
// 是否是图片链接
|
||||||
export const isImgPath = (path: string): boolean => {
|
export const isImgPath = (path: string): boolean => {
|
||||||
return /(https?:\/\/|data:image\/).*?\.(png|jpg|jpeg|gif|svg|webp|ico)/gi.test(path)
|
return /\.(png|jpg|jpeg|gif|svg|webp|ico)(\?.*)?$/i.test(path) || /^data:image\//i.test(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isEmptyVal = (val: any): boolean => {
|
export const isEmptyVal = (val: any): boolean => {
|
||||||
|
|||||||
@ -294,7 +294,22 @@ const getParentName = (parentId: number) => {
|
|||||||
return findParent(treeData.value) || '-'
|
return findParent(treeData.value) || '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取树形数据 */
|
/** 获取树形数据(带搜索条件) */
|
||||||
|
const getTreeListWithSearch = async () => {
|
||||||
|
treeLoading.value = true
|
||||||
|
try {
|
||||||
|
treeData.value = await AreaApi.getAreaTree({
|
||||||
|
name: queryParams.name,
|
||||||
|
type: queryParams.type,
|
||||||
|
level: queryParams.level,
|
||||||
|
status: queryParams.status
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
treeLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取树形数据(默认) */
|
||||||
const getTreeList = async () => {
|
const getTreeList = async () => {
|
||||||
treeLoading.value = true
|
treeLoading.value = true
|
||||||
try {
|
try {
|
||||||
@ -320,11 +335,15 @@ const getList = async () => {
|
|||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.pageNo = 1
|
queryParams.pageNo = 1
|
||||||
getList()
|
getList()
|
||||||
|
// 刷新树形结构(带搜索条件)
|
||||||
|
getTreeListWithSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields()
|
queryFormRef.value.resetFields()
|
||||||
|
// 刷新树形结构(使用默认条件,不带搜索参数)
|
||||||
|
getTreeList()
|
||||||
handleQuery()
|
handleQuery()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,17 @@
|
|||||||
label-width="100px"
|
label-width="100px"
|
||||||
v-loading="formLoading"
|
v-loading="formLoading"
|
||||||
>
|
>
|
||||||
<el-form-item label="所属监区ID" prop="areaId">
|
<el-form-item label="所属监区" prop="areaId">
|
||||||
<el-input v-model="formData.areaId" placeholder="请输入所属监区ID" />
|
<el-tree-select
|
||||||
|
v-model="formData.areaId"
|
||||||
|
:data="areaTreeData"
|
||||||
|
:props="{ label: 'name', value: 'id', children: 'children' }"
|
||||||
|
:render-after-expand="false"
|
||||||
|
default-expand-all
|
||||||
|
check-strictly
|
||||||
|
placeholder="请选择所属监区"
|
||||||
|
class="!w-100%"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="监室名称" prop="name">
|
<el-form-item label="监室名称" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入监室名称" />
|
<el-input v-model="formData.name" placeholder="请输入监室名称" />
|
||||||
@ -16,15 +25,18 @@
|
|||||||
<el-form-item label="监室编码" prop="code">
|
<el-form-item label="监室编码" prop="code">
|
||||||
<el-input v-model="formData.code" placeholder="请输入监室编码" />
|
<el-input v-model="formData.code" placeholder="请输入监室编码" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="床位数量" prop="capacity">
|
<el-row :gutter="20">
|
||||||
<el-input v-model="formData.capacity" placeholder="请输入床位数量" />
|
<el-col :span="12">
|
||||||
</el-form-item>
|
<el-form-item label="床位数量" prop="capacity">
|
||||||
<el-form-item label="当前人数" prop="currentCount">
|
<el-input-number v-model="formData.capacity" :min="0" placeholder="请输入床位数量" controls-position="right" />
|
||||||
<el-input v-model="formData.currentCount" placeholder="请输入当前人数" />
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-col>
|
||||||
<el-form-item label="排序" prop="sort">
|
<el-col :span="12">
|
||||||
<el-input v-model="formData.sort" placeholder="请输入排序" />
|
<el-form-item label="排序" prop="sort">
|
||||||
</el-form-item>
|
<el-input-number v-model="formData.sort" :min="0" placeholder="请输入排序" controls-position="right" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-form-item label="状态" prop="status">
|
<el-form-item label="状态" prop="status">
|
||||||
<el-radio-group v-model="formData.status">
|
<el-radio-group v-model="formData.status">
|
||||||
<el-radio
|
<el-radio
|
||||||
@ -35,7 +47,7 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" :rows="3" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@ -47,6 +59,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
import { CellApi, Cell } from '@/api/prison/cell'
|
import { CellApi, Cell } from '@/api/prison/cell'
|
||||||
|
import { AreaApi } from '@/api/prison/area'
|
||||||
|
|
||||||
/** 监室信息 表单 */
|
/** 监室信息 表单 */
|
||||||
defineOptions({ name: 'CellForm' })
|
defineOptions({ name: 'CellForm' })
|
||||||
@ -58,30 +71,47 @@ const dialogVisible = ref(false) // 弹窗的是否展示
|
|||||||
const dialogTitle = ref('') // 弹窗的标题
|
const dialogTitle = ref('') // 弹窗的标题
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
|
|
||||||
|
// 监区树形数据
|
||||||
|
const areaTreeData = ref<any[]>([])
|
||||||
|
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
areaId: undefined,
|
areaId: undefined as number | undefined,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
code: undefined,
|
code: undefined,
|
||||||
capacity: undefined,
|
capacity: undefined as number | undefined,
|
||||||
currentCount: undefined,
|
currentCount: undefined as number | undefined,
|
||||||
sort: undefined,
|
sort: undefined as number | undefined,
|
||||||
status: undefined,
|
status: undefined as number | undefined,
|
||||||
remark: undefined
|
remark: undefined
|
||||||
})
|
})
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
areaId: [{ required: true, message: '所属监区ID不能为空', trigger: 'blur' }],
|
areaId: [{ required: true, message: '所属监区不能为空', trigger: 'change' }],
|
||||||
name: [{ required: true, message: '监室名称不能为空', trigger: 'blur' }],
|
name: [{ required: true, message: '监室名称不能为空', trigger: 'blur' }],
|
||||||
code: [{ required: true, message: '监室编码不能为空', trigger: 'blur' }],
|
code: [{ required: true, message: '监室编码不能为空', trigger: 'blur' }],
|
||||||
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
|
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
|
||||||
})
|
})
|
||||||
const formRef = ref() // 表单 Ref
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
/** 加载监区树形数据 */
|
||||||
|
const loadAreaTree = async () => {
|
||||||
|
try {
|
||||||
|
areaTreeData.value = await AreaApi.getAreaTree()
|
||||||
|
} catch {
|
||||||
|
areaTreeData.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (type: string, id?: number) => {
|
const open = async (type: string, id?: number) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
dialogTitle.value = t('action.' + type)
|
dialogTitle.value = t('action.' + type)
|
||||||
formType.value = type
|
formType.value = type
|
||||||
|
|
||||||
|
// 加载监区树形数据
|
||||||
|
await loadAreaTree()
|
||||||
|
|
||||||
resetForm()
|
resetForm()
|
||||||
// 修改时,设置数据
|
// 修改时,设置数据
|
||||||
if (id) {
|
if (id) {
|
||||||
|
|||||||
@ -9,12 +9,16 @@
|
|||||||
label-width="80px"
|
label-width="80px"
|
||||||
>
|
>
|
||||||
<el-form-item label="所属监区" prop="areaId">
|
<el-form-item label="所属监区" prop="areaId">
|
||||||
<el-input
|
<el-tree-select
|
||||||
v-model="queryParams.areaId"
|
v-model="queryParams.areaId"
|
||||||
placeholder="请输入监区ID"
|
:data="areaTreeData"
|
||||||
|
:props="{ label: 'name', value: 'id', children: 'children' }"
|
||||||
|
:render-after-expand="false"
|
||||||
|
default-expand-all
|
||||||
|
check-strictly
|
||||||
|
placeholder="请选择监区"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="handleQuery"
|
class="!w-180px"
|
||||||
class="!w-140px"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="监室名称" prop="name">
|
<el-form-item label="监室名称" prop="name">
|
||||||
@ -83,7 +87,7 @@
|
|||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column label="监室ID" align="center" prop="id" width="80" />
|
<el-table-column label="监室ID" align="center" prop="id" width="80" />
|
||||||
<el-table-column label="所属监区" align="center" prop="areaId" width="100" />
|
<el-table-column label="所属监区" align="center" prop="areaName" width="120" />
|
||||||
<el-table-column label="监室名称" align="center" prop="name" width="120" />
|
<el-table-column label="监室名称" align="center" prop="name" width="120" />
|
||||||
<el-table-column label="监室编码" align="center" prop="code" width="120" />
|
<el-table-column label="监室编码" align="center" prop="code" width="120" />
|
||||||
<el-table-column label="床位数量" align="center" prop="capacity" width="90" />
|
<el-table-column label="床位数量" align="center" prop="capacity" width="90" />
|
||||||
@ -136,6 +140,7 @@
|
|||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
import download from '@/utils/download'
|
import download from '@/utils/download'
|
||||||
import { CellApi, Cell } from '@/api/prison/cell'
|
import { CellApi, Cell } from '@/api/prison/cell'
|
||||||
|
import { AreaApi } from '@/api/prison/area'
|
||||||
import CellForm from './CellForm.vue'
|
import CellForm from './CellForm.vue'
|
||||||
|
|
||||||
defineOptions({ name: 'Cell' })
|
defineOptions({ name: 'Cell' })
|
||||||
@ -149,16 +154,28 @@ const total = ref(0)
|
|||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
areaId: undefined,
|
areaId: undefined as number | undefined,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
status: undefined
|
status: undefined
|
||||||
})
|
})
|
||||||
const queryFormRef = ref()
|
const queryFormRef = ref()
|
||||||
const exportLoading = ref(false)
|
const exportLoading = ref(false)
|
||||||
|
|
||||||
|
// 监区树形数据
|
||||||
|
const areaTreeData = ref<any[]>([])
|
||||||
|
|
||||||
// 使用字典获取选项
|
// 使用字典获取选项
|
||||||
const statusOptions = getIntDictOptions(DICT_TYPE.PRISON_CELL_STATUS)
|
const statusOptions = getIntDictOptions(DICT_TYPE.PRISON_CELL_STATUS)
|
||||||
|
|
||||||
|
/** 加载监区树形数据 */
|
||||||
|
const loadAreaTree = async () => {
|
||||||
|
try {
|
||||||
|
areaTreeData.value = await AreaApi.getAreaTree()
|
||||||
|
} catch {
|
||||||
|
areaTreeData.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 日期格式化 */
|
/** 日期格式化 */
|
||||||
const formatDate = (date: string | Date | undefined) => {
|
const formatDate = (date: string | Date | undefined) => {
|
||||||
if (!date) return '-'
|
if (!date) return '-'
|
||||||
@ -235,7 +252,8 @@ const handleExport = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
|
await loadAreaTree()
|
||||||
getList()
|
getList()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -40,8 +40,8 @@
|
|||||||
<el-descriptions-item label="风险等级">
|
<el-descriptions-item label="风险等级">
|
||||||
<dict-tag :type="DICT_TYPE.PRISON_RISK_LEVEL" :value="data.riskLevel" />
|
<dict-tag :type="DICT_TYPE.PRISON_RISK_LEVEL" :value="data.riskLevel" />
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="当前监区">{{ data.areaName }}</el-descriptions-item>
|
<el-descriptions-item label="当前监区">{{ data.prisonAreaName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="当前监室">{{ data.cellName }}</el-descriptions-item>
|
<el-descriptions-item label="当前监室">{{ data.prisonCellName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="状态">
|
<el-descriptions-item label="状态">
|
||||||
<dict-tag :type="DICT_TYPE.PRISONER_STATUS" :value="data.status" />
|
<dict-tag :type="DICT_TYPE.PRISONER_STATUS" :value="data.status" />
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|||||||
@ -225,31 +225,22 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="12">
|
||||||
<el-form-item label="监区" prop="prisonAreaId">
|
<el-form-item label="监区" prop="prisonAreaId">
|
||||||
<el-select v-model="formData.prisonAreaId" placeholder="请选择监区" clearable style="width: 100%" @change="handleAreaChange">
|
<el-tree-select
|
||||||
<el-option
|
v-model="formData.prisonAreaId"
|
||||||
v-for="area in areaList"
|
:data="areaTreeList"
|
||||||
:key="area.id"
|
:props="{ label: 'name', value: 'id', children: 'children' }"
|
||||||
:label="area.name"
|
placeholder="请选择监区"
|
||||||
:value="area.id"
|
clearable
|
||||||
/>
|
filterable
|
||||||
</el-select>
|
style="width: 100%"
|
||||||
|
@change="handleAreaChange"
|
||||||
|
:render-after-expand="false"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="12">
|
||||||
<el-form-item label="分监区" prop="subAreaId">
|
|
||||||
<el-select v-model="formData.subAreaId" placeholder="请选择分监区" clearable style="width: 100%" @change="handleSubAreaChange">
|
|
||||||
<el-option
|
|
||||||
v-for="subArea in subAreaList"
|
|
||||||
:key="subArea.id"
|
|
||||||
:label="subArea.name"
|
|
||||||
:value="subArea.id"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="监室" prop="prisonCellId">
|
<el-form-item label="监室" prop="prisonCellId">
|
||||||
<el-select v-model="formData.prisonCellId" placeholder="请选择监室" clearable style="width: 100%">
|
<el-select v-model="formData.prisonCellId" placeholder="请选择监室" clearable style="width: 100%">
|
||||||
<el-option
|
<el-option
|
||||||
@ -298,8 +289,7 @@ const dialogType = ref<'create' | 'update'>('create')
|
|||||||
const formLoading = ref(false)
|
const formLoading = ref(false)
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const activeTab = ref('basic')
|
const activeTab = ref('basic')
|
||||||
const areaList = ref([])
|
const areaTreeList = ref([])
|
||||||
const subAreaList = ref([])
|
|
||||||
const cellList = ref([])
|
const cellList = ref([])
|
||||||
|
|
||||||
const formData = ref<PrisonerCreateVO>({
|
const formData = ref<PrisonerCreateVO>({
|
||||||
@ -328,7 +318,6 @@ const formData = ref<PrisonerCreateVO>({
|
|||||||
supervisionLevel: undefined,
|
supervisionLevel: undefined,
|
||||||
riskLevel: undefined,
|
riskLevel: undefined,
|
||||||
prisonAreaId: undefined,
|
prisonAreaId: undefined,
|
||||||
subAreaId: undefined,
|
|
||||||
prisonCellId: undefined,
|
prisonCellId: undefined,
|
||||||
status: undefined,
|
status: undefined,
|
||||||
remark: ''
|
remark: ''
|
||||||
@ -348,48 +337,19 @@ const rules = {
|
|||||||
|
|
||||||
/** 加载监区列表 */
|
/** 加载监区列表 */
|
||||||
const loadAreas = async () => {
|
const loadAreas = async () => {
|
||||||
const treeData = await AreaApi.getAreaTree()
|
areaTreeList.value = await AreaApi.getAreaTree()
|
||||||
// 过滤出顶级监区(大队级)
|
|
||||||
areaList.value = treeData.filter((item: any) => item.level === 1 || item.parentId === 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 监区变化时加载分监区 */
|
/** 监区变化时加载监室 */
|
||||||
const handleAreaChange = async (areaId: number) => {
|
const handleAreaChange = async (areaId: number) => {
|
||||||
formData.value.subAreaId = undefined
|
|
||||||
formData.value.prisonCellId = undefined
|
formData.value.prisonCellId = undefined
|
||||||
subAreaList.value = []
|
|
||||||
cellList.value = []
|
cellList.value = []
|
||||||
if (areaId) {
|
if (areaId) {
|
||||||
// 获取子监区(分监区)
|
// 根据监区ID获取监室列表
|
||||||
const treeData = await AreaApi.getAreaTree()
|
cellList.value = await CellApi.getCellPage({ areaId: areaId, pageNo: 1, pageSize: 200 }).then((res: any) => res.list || [])
|
||||||
const area = findArea(treeData, areaId)
|
|
||||||
if (area && area.children) {
|
|
||||||
subAreaList.value = area.children
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 分监区变化时加载监室 */
|
|
||||||
const handleSubAreaChange = async (subAreaId: number) => {
|
|
||||||
formData.value.prisonCellId = undefined
|
|
||||||
cellList.value = []
|
|
||||||
if (subAreaId) {
|
|
||||||
cellList.value = await CellApi.getCellPage({ areaId: subAreaId, pageNo: 1, pageSize: 200 }).then((res: any) => res.list || [])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 递归查找监区 */
|
|
||||||
const findArea = (areas: any[], id: number): any => {
|
|
||||||
for (const area of areas) {
|
|
||||||
if (area.id === id) return area
|
|
||||||
if (area.children) {
|
|
||||||
const found = findArea(area.children, id)
|
|
||||||
if (found) return found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 从身份证号解析出生日期 */
|
/** 从身份证号解析出生日期 */
|
||||||
const parseIdCard = () => {
|
const parseIdCard = () => {
|
||||||
const idCard = formData.value.idCard
|
const idCard = formData.value.idCard
|
||||||
@ -475,12 +435,10 @@ const resetForm = () => {
|
|||||||
supervisionLevel: undefined,
|
supervisionLevel: undefined,
|
||||||
riskLevel: undefined,
|
riskLevel: undefined,
|
||||||
prisonAreaId: undefined,
|
prisonAreaId: undefined,
|
||||||
subAreaId: undefined,
|
|
||||||
prisonCellId: undefined,
|
prisonCellId: undefined,
|
||||||
status: undefined,
|
status: undefined,
|
||||||
remark: ''
|
remark: ''
|
||||||
}
|
}
|
||||||
subAreaList.value = []
|
|
||||||
cellList.value = []
|
cellList.value = []
|
||||||
formRef.value?.resetFields()
|
formRef.value?.resetFields()
|
||||||
}
|
}
|
||||||
@ -494,16 +452,9 @@ const getPrisonerDetail = async (id: number) => {
|
|||||||
...formData.value,
|
...formData.value,
|
||||||
...data
|
...data
|
||||||
}
|
}
|
||||||
// 如果有监区,加载分监区和监室
|
// 如果有监区,加载监室
|
||||||
if (data.prisonAreaId) {
|
if (data.prisonAreaId) {
|
||||||
const treeData = await AreaApi.getAreaTree()
|
cellList.value = await CellApi.getCellPage({ areaId: data.prisonAreaId, pageNo: 1, pageSize: 200 }).then((res: any) => res.list || [])
|
||||||
const area = findArea(treeData, data.prisonAreaId)
|
|
||||||
if (area && area.children) {
|
|
||||||
subAreaList.value = area.children
|
|
||||||
}
|
|
||||||
if (data.subAreaId) {
|
|
||||||
cellList.value = await CellApi.getCellPage({ areaId: data.subAreaId, pageNo: 1, pageSize: 200 }).then((res: any) => res.list || [])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
|
|||||||
@ -72,20 +72,27 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="监区" prop="prisonAreaId">
|
<el-form-item label="监区" prop="prisonAreaId">
|
||||||
<el-select
|
<el-tree-select
|
||||||
v-model="queryParams.prisonAreaId"
|
v-model="queryParams.prisonAreaId"
|
||||||
|
:data="areaTreeList"
|
||||||
|
:props="{ label: 'name', value: 'id', children: 'children' }"
|
||||||
placeholder="请选择监区"
|
placeholder="请选择监区"
|
||||||
clearable
|
clearable
|
||||||
|
filterable
|
||||||
class="!w-240px"
|
class="!w-240px"
|
||||||
@change="handleAreaChange"
|
@change="handleAreaChange"
|
||||||
>
|
:render-after-expand="false"
|
||||||
<el-option
|
/>
|
||||||
v-for="area in areaList"
|
</el-form-item>
|
||||||
:key="area.id"
|
<el-form-item label="入狱日期" prop="imprisonmentDate">
|
||||||
:label="area.name"
|
<el-date-picker
|
||||||
:value="area.id"
|
v-model="queryParams.imprisonmentDate"
|
||||||
/>
|
type="daterange"
|
||||||
</el-select>
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
class="!w-240px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="监室" prop="prisonCellId">
|
<el-form-item label="监室" prop="prisonCellId">
|
||||||
<el-select
|
<el-select
|
||||||
@ -164,7 +171,11 @@
|
|||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column label="罪犯编号" align="center" prop="prisonerNo" width="120" />
|
<el-table-column label="罪犯编号" align="center" prop="prisonerNo" width="120" />
|
||||||
<el-table-column label="姓名" align="center" prop="name" width="100" />
|
<el-table-column label="姓名" align="center" prop="name" width="100" />
|
||||||
<el-table-column label="性别" align="center" prop="genderName" width="80" />
|
<el-table-column label="性别" align="center" prop="gender" width="80">
|
||||||
|
<template #default="scope">
|
||||||
|
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.gender" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="身份证号" align="center" prop="idCard" width="180">
|
<el-table-column label="身份证号" align="center" prop="idCard" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatIdCard(scope.row.idCard) }}
|
{{ formatIdCard(scope.row.idCard) }}
|
||||||
@ -177,11 +188,23 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="入狱日期" align="center" prop="imprisonmentDate" width="120" />
|
<el-table-column label="入狱日期" align="center" prop="imprisonmentDate" width="120" />
|
||||||
<el-table-column label="监管等级" align="center" prop="supervisionLevelName" width="100" />
|
<el-table-column label="监管等级" align="center" prop="supervisionLevel" width="100">
|
||||||
<el-table-column label="风险等级" align="center" prop="riskLevelName" width="100" />
|
<template #default="scope">
|
||||||
|
<dict-tag :type="DICT_TYPE.PRISON_SUPERVISION_LEVEL" :value="scope.row.supervisionLevel" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="风险等级" align="center" prop="riskLevel" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<dict-tag :type="DICT_TYPE.PRISON_RISK_LEVEL" :value="scope.row.riskLevel" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="当前监区" align="center" prop="prisonAreaName" width="120" />
|
<el-table-column label="当前监区" align="center" prop="prisonAreaName" width="120" />
|
||||||
<el-table-column label="当前监室" align="center" prop="prisonCellName" width="100" />
|
<el-table-column label="当前监室" align="center" prop="prisonCellName" width="100" />
|
||||||
<el-table-column label="状态" align="center" prop="statusName" width="100" />
|
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<dict-tag :type="DICT_TYPE.PRISONER_STATUS" :value="scope.row.status" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" width="240">
|
<el-table-column label="操作" align="center" width="240">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
@ -258,7 +281,7 @@ const message = useMessage() // 消息弹窗
|
|||||||
const loading = ref(true) // 列表的加载中
|
const loading = ref(true) // 列表的加载中
|
||||||
const total = ref(0) // 列表的总页数
|
const total = ref(0) // 列表的总页数
|
||||||
const list = ref([]) // 列表的数据
|
const list = ref([]) // 列表的数据
|
||||||
const areaList = ref([]) // 监区列表
|
const areaTreeList = ref([]) // 监区树形列表
|
||||||
const cellList = ref([]) // 监室列表
|
const cellList = ref([]) // 监室列表
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
@ -272,6 +295,7 @@ const queryParams = reactive({
|
|||||||
prisonAreaId: undefined,
|
prisonAreaId: undefined,
|
||||||
prisonCellId: undefined,
|
prisonCellId: undefined,
|
||||||
status: undefined,
|
status: undefined,
|
||||||
|
imprisonmentDate: [] as string[], // 日期范围数组
|
||||||
imprisonmentDateStart: undefined,
|
imprisonmentDateStart: undefined,
|
||||||
imprisonmentDateEnd: undefined
|
imprisonmentDateEnd: undefined
|
||||||
})
|
})
|
||||||
@ -285,6 +309,14 @@ const transferRef = ref() // 调监表单
|
|||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
// 处理日期范围
|
||||||
|
if (queryParams.imprisonmentDate && queryParams.imprisonmentDate.length === 2) {
|
||||||
|
queryParams.imprisonmentDateStart = queryParams.imprisonmentDate[0]
|
||||||
|
queryParams.imprisonmentDateEnd = queryParams.imprisonmentDate[1]
|
||||||
|
} else {
|
||||||
|
queryParams.imprisonmentDateStart = undefined
|
||||||
|
queryParams.imprisonmentDateEnd = undefined
|
||||||
|
}
|
||||||
const data = await PrisonerApi.getPrisonerPage(queryParams)
|
const data = await PrisonerApi.getPrisonerPage(queryParams)
|
||||||
list.value = data.list
|
list.value = data.list
|
||||||
total.value = data.total
|
total.value = data.total
|
||||||
@ -303,6 +335,9 @@ const handleQuery = () => {
|
|||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value.resetFields()
|
queryFormRef.value.resetFields()
|
||||||
queryParams.prisonCellId = undefined
|
queryParams.prisonCellId = undefined
|
||||||
|
queryParams.imprisonmentDate = []
|
||||||
|
queryParams.imprisonmentDateStart = undefined
|
||||||
|
queryParams.imprisonmentDateEnd = undefined
|
||||||
handleQuery()
|
handleQuery()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +391,7 @@ const handleAreaChange = async (areaId: number) => {
|
|||||||
|
|
||||||
/** 加载监区列表 */
|
/** 加载监区列表 */
|
||||||
const loadAreas = async () => {
|
const loadAreas = async () => {
|
||||||
areaList.value = await AreaApi.getAreaTree()
|
areaTreeList.value = await AreaApi.getAreaTree()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 身份证脱敏显示 */
|
/** 身份证脱敏显示 */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user