feat:人闸统计

This commit is contained in:
dzc committed 2025-07-21 17:39:31 +08:00
1 parent f18796aef3
commit 98471ceae4
7 files changed
+240 -15

No files matched your search

+8
View File
@@ -34,6 +34,14 @@ export function editBindDevice(data: any) {
})
}
export function getDevice(params: any) {
return request({
url: '/admin/areaHouse/getDevice',
method: 'get',
params
})
}
/**
* 删除房间绑定设备
*/
+13
View File
@@ -1,5 +1,18 @@
import request from "/@/utils/request"
export function cameraPage(query: any) {
return request({
url: '/admin/deviceManage/cameraPage',
method: 'post',
params: {
current: query.current,
size: query.size,
},
data: query
})
}
export function fetchList(query: any) {
return request({
url: '/admin/deviceManage/page',
+23 -10
View File
@@ -5,7 +5,12 @@
<el-row :gutter="24">
<el-col :span="24" class="mb20">
<el-form-item label="房间名" prop="name">
<el-input v-model="form.name" disabled placeholder="Please input" />
<el-input v-model="form.name" disabled placeholder="" />
</el-form-item>
</el-col>
<el-col :span="24" class="mb20" v-if="form.id">
<el-form-item label="唯一编码" prop="uniqueCode">
<el-input v-model="form.uniqueCode" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="24" class="mb20">
@@ -50,6 +55,7 @@ const form = reactive<any>({
// 定义校验规则
const dataRules = ref({
name: [{ required: true, message: '房间名不能为空', trigger: 'change' }],
uniqueCode: [{ required: true, message: '唯一编码不能为空', trigger: 'change' }],
deviceId: [{ required: true, message: '设备不能为空', trigger: 'change' }],
})
@@ -63,17 +69,14 @@ const openDialog = (areaHouseId: string, bindId?: string) => {
dataFormRef.value?.resetFields();
});
// 获取areaHouse信息
if (areaHouseId) {
form.areaHouseId = areaHouseId
getareaHouseData(areaHouseId)
}
if (areaHouseId) form.areaHouseId = areaHouseId
getareaHouseDeviceData(bindId, areaHouseId)
};
// 提交
const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => { });
if (!valid) return false;
try {
loading.value = true;
form.id ? await AreaHouseApi.editBindDevice(form) : await AreaHouseApi.bindDevice(form);
@@ -89,13 +92,23 @@ const onSubmit = async () => {
// 初始化表单数据
const getareaHouseData = async (id: string) => {
const getareaHouseDeviceData = async (bindId: any, areaHouseId: any) => {
// 获取数据
loading.value = true
try {
const { data } = await AreaHouseApi.getObj(id)
if (data) {
form.name = data.name
if (bindId) {
// 房间设备绑定详情
const { data: houseDeviceRes } = await AreaHouseApi.getDevice({ id: bindId })
if (houseDeviceRes) {
form.name = houseDeviceRes.houseName
form.uniqueCode = houseDeviceRes.uniqueCode
form.deviceId = houseDeviceRes.deviceId
}
} else if (areaHouseId) {
const { data: houseRes } = await AreaHouseApi.getObj(areaHouseId)
if (houseRes) {
form.name = houseRes.name
}
}
} catch (error: any) {
console.error(error);
+13 -4
View File
@@ -1,8 +1,8 @@
<template>
<el-dialog title="绑定摄像头" v-model="visible" width="70%" :close-on-click-modal="false" draggable>
<el-dialog title="绑定摄像头" v-model="visible" width="80%" :close-on-click-modal="false" draggable>
<div class="mb12" style="width: 100%">
<el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog(
state.queryForm.areaId
state.queryForm.houseId
)">
绑定相机
</el-button>
@@ -12,6 +12,13 @@
@sort-change="sortChangeHandle">
<el-table-column type="selection" width="40" align="center" />
<el-table-column type="index" label="#" width="80" />
<el-table-column prop="uniqueCode" width="200" label="空间">
<template #default="{ row }">
<div>
<div>{{ row.uniqueCode }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="空间">
<el-table-column prop="areaName" label="空间名" />
<el-table-column prop="areaUniqueCode" width="120" label="空间编码" />
@@ -40,7 +47,7 @@
<el-button icon="VideoPlay" text type="primary"
@click="previewVideoDialogRef.openDialog(row.deviceId)">预览</el-button>
<el-button icon="edit-pen" text type="primary" v-auth="'area_areaHouse_edit'"
@click="formDialogRef.openDialog(state.queryForm.areaId, row.id)">编辑</el-button>
@click="formDialogRef.openDialog(state.queryForm.houseId, row.id)">编辑</el-button>
<el-button icon="delete" text type="primary" v-auth="'area_areaHouse_del'"
@click="handleDelete([row.id])">删除</el-button>
</template>
@@ -61,6 +68,8 @@
</template>
<script setup lang="ts" name="BindCameraTable">
import { CopyDocument } from "@element-plus/icons-vue"
import { BasicTableProps, useTable } from "/@/hooks/table";
import { useMessage, useMessageBox } from "/@/hooks/message";
@@ -109,7 +118,7 @@ const openDialog = (id: string) => {
visible.value = true
// 获取areaHouse信息
if (id) {
state.queryForm.areaId = id
state.queryForm.houseId = id
getDataList()
}
};
+182
View File
@@ -0,0 +1,182 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<draggable-org-Tree ref="draggableDepTreeRef" placeholder="请输入部门名称" :show-expand="true"
@getSelectNode="handleGetSelectNode" switch-inactive-text="包含" switch-active-text="不包含"
:defaultTreeWidth="20" :nodeClickable="false">
<template #default>
<el-row shadow="hover" v-show="showSearch" class="ml10">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item style="width: 250px;" label="设备名" prop="deviceName">
<el-input v-model="state.queryForm.deviceName" placeholder="请输入设备名" />
</el-form-item>
<el-form-item style="width: 250px;" label="设备类型" prop="deviceCategory">
<dict-select v-model="state.queryForm.deviceCategory" :options="device_category" />
</el-form-item>
<el-form-item style="width: 250px;" label="状态" prop="isOnline">
<dict-select v-model="state.queryForm.isOnline" :options="is_nline" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog()"
v-auth="'admin_deviceManage_add'">
新 增
</el-button>
<el-button plain :disabled="multiple" icon="Delete" type="primary"
v-auth="'admin_deviceManage_del'" @click="handleDelete(selectObjs)">
删除
</el-button>
<right-toolbar v-model:showSearch="showSearch" :export="'admin_deviceManage_export'"
@exportExcel="exportExcel" class="ml10 mr20" style="float: right;"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" border :cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle" @selection-change="selectionChangHandle"
@sort-change="sortChangeHandle">
<el-table-column type="selection" width="40" align="center" />
<el-table-column type="index" label="#" width="80" />
<el-table-column prop="deviceCode" align="left" min-width="100" label="设备编码" />
<el-table-column prop="deviceName" align="left" min-width="150" label="设备名称" />
<el-table-column prop="deviceIp" align="left" min-width="150" label="ip" />
<el-table-column prop="devicePort" align="left" min-width="100" label="端口" />
<el-table-column prop="deviceCategory" align="left" min-width="150" label="设备大类">
<template #default="{ row }">
<dict-tag :options="device_category" :value="row.deviceCategory" />
</template>
</el-table-column>
<el-table-column prop="deviceManufacturer" align="left" min-width="100" label="厂商类型">
<template #default="{ row }">
<dict-tag :options="dh_device_manufacturer" :value="row.deviceManufacturer" />
</template>
</el-table-column>
<el-table-column prop="orgName" align="left" min-width="150" label="设备所属组织" />
<el-table-column prop="isOnline" align="left" min-width="120" label="状态">
<template #default="{ row }">
<tag-online :isOnline="row.isOnline == 1" />
</template>
</el-table-column>
<el-table-column prop="isSync" align="left" min-width="120" label="同步状态">
<template #default="{ row }">
<tag-sync :isSync="row.isSync == 1" />
</template>
</el-table-column>
<el-table-column prop="offlineReason" align="left" min-width="120" label="离线原因">
<template #default="{ row }">
{{ row.offlineReason }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200">
<template #default="scope">
<el-button icon="VideoPlay" text type="primary"
@click="previewVideoRef.openDialog(scope.row.id)">预览</el-button>
<el-button icon="edit-pen" text type="primary" v-auth="'admin_deviceManage_edit'"
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
<el-button icon="delete" text type="primary" v-auth="'admin_deviceManage_del'"
@click="handleDelete([scope.row.id])">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
v-bind="state.pagination" />
</template>
</draggable-org-Tree>
</div>
<!-- 编辑、新增 -->
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
<preview-video ref="previewVideoRef" />
</div>
</template>
<script setup lang="ts" name="systemDeviceManage">
import { BasicTableProps, useTable } from "/@/hooks/table";
import * as DeviceManageApi from "/@/api/device/deviceManage";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useDict } from '/@/hooks/dict';
// 引入组件
const FormDialog = defineAsyncComponent(() => import("../components/deviceForm.vue"));
const PreviewVideo = defineAsyncComponent(() => import("../components/preview-video/index.vue"));
// 定义查询字典
const { device_category, is_sync, is_nline, dh_device_manufacturer } = useDict("device_category", "is_sync", "is_nline", "dh_device_manufacturer")
// 定义变量内容
const formDialogRef = ref()
const previewVideoRef = ref()
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
// 多选变量
const selectObjs = ref([]) as any
const multiple = ref(true)
const draggableDepTreeRef = ref()
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: DeviceManageApi.cameraPage
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile,
tableStyle
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
// 清空多选
selectObjs.value = []
draggableDepTreeRef.value.resetData()
getDataList()
}
// 导出excel
const exportExcel = () => {
downBlobFile('/admin/deviceManage/export', Object.assign(state.queryForm, { ids: selectObjs }), 'deviceManage.xlsx')
}
// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
selectObjs.value = objs.map(({ id }) => id);
multiple.value = !objs.length;
};
// 树节点选择时
const handleGetSelectNode = (curClickedNode: any, checkedTreeNodes: any, isDeepTree: boolean) => {
state.queryForm.ownerCode = curClickedNode.id
state.queryForm.orgCodes = checkedTreeNodes.map((item: any) => item.id)
state.queryForm.isInclude = !isDeepTree
getDataList()
}
// 删除操作
const handleDelete = async (ids: string[]) => {
try {
await useMessageBox().confirm('此操作将永久删除');
} catch {
return;
}
try {
await DeviceManageApi.delObjs(ids);
getDataList();
useMessage().success('删除成功');
} catch (err: any) {
useMessage().error(err.msg);
}
};
</script>
+1 -1
View File
@@ -103,7 +103,7 @@ import { useMessage, useMessageBox } from "/@/hooks/message";
import { useDict } from '/@/hooks/dict';
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const FormDialog = defineAsyncComponent(() => import('../components/deviceForm.vue'));
const PreviewVideo = defineAsyncComponent(() => import("../components/preview-video/index.vue"));
// 定义查询字典
const { device_category, is_sync, is_nline, dh_device_manufacturer } = useDict("device_category", "is_sync", "is_nline", "dh_device_manufacturer")