yxq 2 months ago
parent
commit
b5b185c377
9 changed files with 272 additions and 44 deletions
  1. +1
    -1
      SafeCampus.WEB/.env
  2. +7
    -0
      SafeCampus.WEB/src/api/interface/sys/monitor/camera.ts
  3. +12
    -0
      SafeCampus.WEB/src/api/modules/monitor/live.ts
  4. +9
    -1
      SafeCampus.WEB/src/enums/formEnum.ts
  5. +1
    -0
      SafeCampus.WEB/src/views/monitor/live/components/form.vue
  6. +47
    -23
      SafeCampus.WEB/src/views/monitor/live/components/userForm.vue
  7. +8
    -10
      SafeCampus.WEB/src/views/monitor/live/index.vue
  8. +151
    -0
      SafeCampus.WEB/src/views/sysconfig/ability/components/userForm.vue
  9. +36
    -9
      SafeCampus.WEB/src/views/sysconfig/ability/index.vue

+ 1
- 1
SafeCampus.WEB/.env View File

@@ -1,5 +1,5 @@
# title # title
VITE_GLOB_APP_TITLE = 校园监控智能分析平台
VITE_GLOB_APP_TITLE = AI监控预警分析平台


# 本地运行端口号 # 本地运行端口号
VITE_PORT = 8848 VITE_PORT = 8848


+ 7
- 0
SafeCampus.WEB/src/api/interface/sys/monitor/camera.ts View File

@@ -57,4 +57,11 @@ export namespace sysCamera {
id: number | string; id: number | string;
name: string; name: string;
} }
// 设置推送人
export interface setGroup {
/** groupId */
groupId: number | string;
userId: number | string;
ids: number | string[];
}
} }

+ 12
- 0
SafeCampus.WEB/src/api/modules/monitor/live.ts View File

@@ -44,6 +44,18 @@ const monitorLIVEApi = {
setGroup(params: sysCamera.setGroup) { setGroup(params: sysCamera.setGroup) {
return http2.post<ResPage<sysCamera.MonitorInfo>>("batchSetGroup", params); return http2.post<ResPage<sysCamera.MonitorInfo>>("batchSetGroup", params);
}, },
// 根据分组批量设置推送人
setPushPerson(params: sysCamera.setGroup) {
return http2.post<ResPage<sysCamera.MonitorInfo>>("batchSetPushPersonByGroup", params);
},
// 对摄像头批量设置推送人
setVideoPushPerson(params: sysCamera.setGroup) {
return http2.post<ResPage<sysCamera.MonitorInfo>>("batchSetPushPerson", params);
},
// 对摄像头批量设置推送人
setWarningPushPerson(params: sysCamera.setGroup) {
return http2.post<ResPage<sysCamera.MonitorInfo>>("batchSetPushPersonByWarn", params);
},
// 获取摄像头分组树 // 获取摄像头分组树
groupList(params: sysCamera.Tree) { groupList(params: sysCamera.Tree) {
return http3.get<ResPage<sysCamera.MonitorInfo>>("getNoPageList"); return http3.get<ResPage<sysCamera.MonitorInfo>>("getNoPageList");


+ 9
- 1
SafeCampus.WEB/src/enums/formEnum.ts View File

@@ -22,5 +22,13 @@ export enum FormOptEnum {
/** 查看 */ /** 查看 */
VIEW = "查看", VIEW = "查看",
/** 删除 */ /** 删除 */
DELETE = "删除"
DELETE = "删除",
// 分组推送人
GroupPushPerson = "分组推送人",
// 视频推送人
VideoPushPerson = "视频推送人",
// 移动
MOVE = "移动",
// 分组
GROUP = "分组"
} }

+ 1
- 0
SafeCampus.WEB/src/views/monitor/live/components/form.vue View File

@@ -78,6 +78,7 @@ function onOpen(props: FormProps.Base<SysOrg.SysOrgInfo>) {
visible.value = true; //显示表单 visible.value = true; //显示表单
if (props.record.id) { if (props.record.id) {
//如果传了id,就去请求api获取record //如果传了id,就去请求api获取record
return;
bizOrgApi.detail({ id: props.record.id }).then(res => { bizOrgApi.detail({ id: props.record.id }).then(res => {
orgProps.record = res.data; orgProps.record = res.data;
}); });


+ 47
- 23
SafeCampus.WEB/src/views/monitor/live/components/userForm.vue View File

@@ -15,10 +15,10 @@
label-width="auto" label-width="auto"
label-suffix=" :" label-suffix=" :"
> >
<s-form-item label="指定分组推送人" prop="directorId">
<s-form-item label="指定分组推送人" prop="userId">
<el-button link type="primary" @click="showSelector">选择</el-button> <el-button link type="primary" @click="showSelector">选择</el-button>
<el-tag v-if="liveUserProps.record.directorId" class="ml-3px" type="warning" closable @close="removeDirector">{{
liveUserProps.record.directorInfo?.name
<el-tag v-if="liveUserProps.record.userId" class="ml-3px" type="warning" closable @close="removeDirector">{{
liveUserProps.record.userInfo?.name
}}</el-tag> }}</el-tag>
</s-form-item> </s-form-item>
</el-form> </el-form>
@@ -32,7 +32,7 @@
</template> </template>


<script setup lang="ts"> <script setup lang="ts">
import { SysOrg, SysUser, sysOrgApi, sysPositionApi, sysRoleApi, sysUserApi } from "@/api";
import { SysOrg, SysUser, sysOrgApi, sysPositionApi, sysRoleApi, sysUserApi, monitorLIVEApi } from "@/api";
import { FormOptEnum, SysDictEnum } from "@/enums"; import { FormOptEnum, SysDictEnum } from "@/enums";
import { required } from "@/utils/formRules"; import { required } from "@/utils/formRules";
import { FormInstance } from "element-plus"; import { FormInstance } from "element-plus";
@@ -51,7 +51,7 @@ const liveUserProps = reactive<FormProps.Base<SysOrg.SysOrgInfo>>({


// 表单验证规则 // 表单验证规则
const rules = reactive({ const rules = reactive({
directorId: [required("请选择指定分组推送人")]
userId: [required("请选择指定分组推送人")]
}); });


/** /**
@@ -78,16 +78,40 @@ const userFormRef = ref<FormInstance>();
async function handleSubmit() { async function handleSubmit() {
userFormRef.value?.validate(async valid => { userFormRef.value?.validate(async valid => {
if (!valid) return; //表单验证失败 if (!valid) return; //表单验证失败
return;
//提交表单
await sysOrgApi
.submitForm(liveUserProps.record, liveUserProps.record.id != undefined)
.then(() => {
liveUserProps.successful!(); //调用父组件的successful方法
})
.finally(() => {
onClose();
});
console.log(liveUserProps, 888);
let params: any = {
groupId: "",
userId: "",
ids: []
};
if (liveUserProps.opt == "分组推送人") {
params.groupId = liveUserProps.record.id;
params.userId = liveUserProps.record.userId;
//提交表单
await monitorLIVEApi
.setPushPerson(params)
.then(() => {
liveUserProps.successful!(); //调用父组件的successful方法
})
.finally(() => {
onClose();
});
} else {
params.userId = liveUserProps.record.userId;
params.ids.push(liveUserProps.record.id);
//提交表单
await monitorLIVEApi
.setVideoPushPerson(params)
.then(() => {
liveUserProps.successful!(); //调用父组件的successful方法
})
.finally(() => {
onClose();
});
// delete params.
}
// console.log(params);
// return;
}); });
} }


@@ -99,24 +123,24 @@ function onClose() {
const userSelectorRef = ref<UserSelectorInstance>(); //用户选择器引用 const userSelectorRef = ref<UserSelectorInstance>(); //用户选择器引用
/** 显示用户选择器 */ /** 显示用户选择器 */
function showSelector() { function showSelector() {
//将liveUserProps.record.directorInfo转为 SysUser.SysUserInfo[]类型
const directorInfo = liveUserProps.record.directorInfo ? [liveUserProps.record.directorInfo] : [];
userSelectorRef.value?.showSelector(directorInfo);
//将liveUserProps.record.userInfo转为 SysUser.SysUserInfo[]类型
const userInfo = liveUserProps.record.userInfo ? [liveUserProps.record.userInfo] : [];
userSelectorRef.value?.showSelector(userInfo);
} }


/** 选择用户 */ /** 选择用户 */
function handleChooseUser(data: SysUser.SysUserInfo[]) { function handleChooseUser(data: SysUser.SysUserInfo[]) {
// 选择用户后,将用户id赋值给liveUserProps.record.directorId
// 选择用户后,将用户id赋值给liveUserProps.record.userId
if (data.length > 0) { if (data.length > 0) {
liveUserProps.record.directorId = data[0].id;
liveUserProps.record.directorInfo = data[0];
liveUserProps.record.userId = data[0].id;
liveUserProps.record.userInfo = data[0];
} }
} }


/** 移除主管 */ /** 移除主管 */
function removeDirector() { function removeDirector() {
liveUserProps.record.directorId = null;
liveUserProps.record.directorInfo = null;
liveUserProps.record.userId = null;
liveUserProps.record.userInfo = null;
} }
// 暴露给父组件的方法 // 暴露给父组件的方法
defineExpose({ defineExpose({


+ 8
- 10
SafeCampus.WEB/src/views/monitor/live/index.vue View File

@@ -30,9 +30,11 @@
<span class="custom-tree-node"> <span class="custom-tree-node">
<span class="node-label" :title="node.label">{{ node.label }}</span> <span class="node-label" :title="node.label">{{ node.label }}</span>
<span v-if="data.id && data.id != '-1'"> <span v-if="data.id && data.id != '-1'">
<el-icon size="16" title="添加" @click.stop="append('add', data)"><CirclePlus /></el-icon>
<!-- <el-icon size="16" title="添加" @click.stop="append('add', data)"><CirclePlus /></el-icon> -->
<el-icon size="16" title="编辑" @click.stop="append('edit', data)" style="margin-left: 8px"><Edit /></el-icon> <el-icon size="16" title="编辑" @click.stop="append('edit', data)" style="margin-left: 8px"><Edit /></el-icon>
<el-icon size="16" title="设置推送人" @click.stop="pushPerson('push', data)" style="margin-left: 8px"><UserFilled /></el-icon>
<el-icon size="16" title="设置推送人" @click.stop="pushPerson(FormOptEnum.GroupPushPerson, data)" style="margin-left: 8px"
><UserFilled
/></el-icon>
<el-icon size="16" title="删除" @click.stop="remove(data.id, '删除该分组')" style="margin-left: 8px"><Delete /></el-icon> <el-icon size="16" title="删除" @click.stop="remove(data.id, '删除该分组')" style="margin-left: 8px"><Delete /></el-icon>
</span> </span>
</span> </span>
@@ -61,7 +63,8 @@
<s-button link :opt="FormOptEnum.EDIT" @click="onOpen(FormOptEnum.EDIT, scope.row)">编辑</s-button> <s-button link :opt="FormOptEnum.EDIT" @click="onOpen(FormOptEnum.EDIT, scope.row)">编辑</s-button>
<s-button link :opt="FormOptEnum.VIEW" @click="onDetail(scope.row)"> 查看 </s-button> <s-button link :opt="FormOptEnum.VIEW" @click="onDetail(scope.row)"> 查看 </s-button>
<s-button link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.id], `确定删除该摄像头吗?`)" /> <s-button link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.id], `确定删除该摄像头吗?`)" />
<s-button link :opt="FormOptEnum.VIEW" @click="pushPerson(scope.row)"> 推送人 </s-button>
<!-- <el-button link type="primary" :icon="Avatar" /> -->
<s-button link :opt="FormOptEnum.VIEW" @click="pushPerson(FormOptEnum.VideoPushPerson, scope.row)"> 推送人 </s-button>
</template> </template>
</ProTable> </ProTable>
<!-- 添加分组弹框 --> <!-- 添加分组弹框 -->
@@ -116,7 +119,7 @@ import VideoPlay from "@/components/VideoPlay/videoplay.vue";
import { ElMessage, ElMessageBox, ElTree } from "element-plus"; import { ElMessage, ElMessageBox, ElTree } from "element-plus";
import type Node from "element-plus/es/components/tree/src/model/node"; import type Node from "element-plus/es/components/tree/src/model/node";
import { monitorLIVEApi, monitorLiveButtonCode } from "@/api"; import { monitorLIVEApi, monitorLiveButtonCode } from "@/api";
import { ZJRQ } from "@/api/interface";
import { sysCamera } from "@/api/interface";
import { useHandleData } from "@/hooks/useHandleData"; import { useHandleData } from "@/hooks/useHandleData";
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
import { useDictStore } from "@/stores/modules"; import { useDictStore } from "@/stores/modules";
@@ -234,11 +237,6 @@ const handleNodeClick = (data: Tree) => {
proTable.value!.searchParam.groupId = data.id; proTable.value!.searchParam.groupId = data.id;
proTable.value!.search(); proTable.value!.search();
}; };

// 设置分组推送人
// async function pushPerson(type:string,data: Tree) {

// }
const visible = ref(false); //是否显示表单 const visible = ref(false); //是否显示表单


// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) // 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数)
@@ -246,7 +244,7 @@ const proTable = ref<ProTableInstance>();
const dictStore = useDictStore(); const dictStore = useDictStore();


// 表格配置项 // 表格配置项
const columns: ColumnProps<ZJRQ.WarnInfo>[] = [
const columns: ColumnProps<sysCamera.MonitorInfo>[] = [
{ type: "selection", fixed: "left", width: 80 }, { type: "selection", fixed: "left", width: 80 },
{ {
prop: "sensorId", prop: "sensorId",


+ 151
- 0
SafeCampus.WEB/src/views/sysconfig/ability/components/userForm.vue View File

@@ -0,0 +1,151 @@
<!--
* @Description: 表单
* @Author: huguodong
* @Date: 2023-12-15 15:45:28
!-->
<template>
<div>
<form-container v-model="visible" title="人员选择" form-size="600px">
<el-form
ref="userFormRef"
:rules="rules"
:disabled="liveUserProps.disabled"
:model="liveUserProps.record"
:hide-required-asterisk="liveUserProps.disabled"
label-width="auto"
label-suffix=" :"
>
<s-form-item label="指定分组推送人" prop="userId">
<el-button link type="primary" @click="showSelector">选择</el-button>
<el-tag v-if="liveUserProps.record.userId" class="ml-3px" type="warning" closable @close="removeDirector">{{
liveUserProps.record.userInfo?.name
}}</el-tag>
</s-form-item>
</el-form>
<template #footer>
<el-button @click="onClose"> 取消 </el-button>
<el-button v-show="!liveUserProps.disabled" type="primary" @click="handleSubmit"> 确定 </el-button>
</template>
</form-container>
<user-selector ref="userSelectorRef" :org-tree-api="sysOrgApi.tree" :user-selector-api="sysUserApi.selector" @successful="handleChooseUser" />
</div>
</template>

<script setup lang="ts">
import { SysOrg, SysUser, sysOrgApi, sysPositionApi, sysRoleApi, sysUserApi, monitorLIVEApi } from "@/api";
import { FormOptEnum, SysDictEnum } from "@/enums";
import { required } from "@/utils/formRules";
import { FormInstance } from "element-plus";
import { useDictStore } from "@/stores/modules";
import { UserSelectorInstance } from "@/components/Selectors/UserSelector/interface";

const visible = ref(false); //是否显示表单
const dictStore = useDictStore(); //字典仓库

// 表单参数
const liveUserProps = reactive<FormProps.Base<SysOrg.SysOrgInfo>>({
opt: FormOptEnum.ADD,
record: {},
disabled: false
});

// 表单验证规则
const rules = reactive({
userId: [required("请选择指定分组推送人")]
});

/**
* 打开表单
* @param props 表单参数
*/
function onOpen(props: FormProps.Base<SysOrg.SysOrgInfo>) {
Object.assign(liveUserProps, props); //合并参数
if (props.opt == FormOptEnum.ADD) {
//如果是新增,设置默认值
}
visible.value = true; //显示表单
// if (props.record.id) {
// //如果传了id,就去请求api获取record
// sysOrgApi.detail({ id: props.record.id }).then(res => {
// liveUserProps.record = res.data;
// });
// }
}

// 提交数据(新增/编辑)
const userFormRef = ref<FormInstance>();
/** 提交表单 */
async function handleSubmit() {
userFormRef.value?.validate(async valid => {
if (!valid) return; //表单验证失败
console.log(liveUserProps, 888);
let params: any = {
groupId: "",
userId: "",
ids: []
};
if (liveUserProps.opt == "分组推送人") {
params.groupId = liveUserProps.record.id;
params.userId = liveUserProps.record.userId;
//提交表单
await monitorLIVEApi
.setPushPerson(params)
.then(() => {
liveUserProps.successful!(); //调用父组件的successful方法
})
.finally(() => {
onClose();
});
} else {
params.userId = liveUserProps.record.userId;
params.warnCode = liveUserProps.record.code;
//提交表单
await monitorLIVEApi
.setWarningPushPerson(params)
.then(() => {
liveUserProps.successful!(); //调用父组件的successful方法
})
.finally(() => {
onClose();
});
// delete params.
}
// console.log(params);
// return;
});
}

/** 关闭表单*/
function onClose() {
visible.value = false;
}

const userSelectorRef = ref<UserSelectorInstance>(); //用户选择器引用
/** 显示用户选择器 */
function showSelector() {
//将liveUserProps.record.userInfo转为 SysUser.SysUserInfo[]类型
const userInfo = liveUserProps.record.userInfo ? [liveUserProps.record.userInfo] : [];
userSelectorRef.value?.showSelector(userInfo);
}

/** 选择用户 */
function handleChooseUser(data: SysUser.SysUserInfo[]) {
// 选择用户后,将用户id赋值给liveUserProps.record.userId
if (data.length > 0) {
liveUserProps.record.userId = data[0].id;
liveUserProps.record.userInfo = data[0];
}
}

/** 移除主管 */
function removeDirector() {
liveUserProps.record.userId = null;
liveUserProps.record.userInfo = null;
}
// 暴露给父组件的方法
defineExpose({
onOpen
});
</script>

<style lang="scss" scoped></style>

+ 36
- 9
SafeCampus.WEB/src/views/sysconfig/ability/index.vue View File

@@ -5,16 +5,32 @@
!--> !-->
<template> <template>
<div class="abilityBox"> <div class="abilityBox">
<TreeFilter ref="treeFilter" label="name" id="id" width="300px" :request-api="monitorLIVEApi.groupList" @change="changeGroup"> </TreeFilter>
<TreeFilter ref="treeFilter" title="摄像头分组" label="name" id="id" width="300px" :request-api="monitorLIVEApi.groupList" @change="changeGroup">
</TreeFilter>


<TreeFilter ref="treeFilters" label="sensorName" id="sensorId" :isData="true" width="300px" :data="videoList" @change="changeVideo"> </TreeFilter>
<TreeFilter
ref="treeFilters"
title="摄像头列表"
label="sensorName"
id="sensorId"
:isData="true"
width="300px"
:data="videoList"
@change="changeVideo"
>
</TreeFilter>


<div class="card content-main"> <div class="card content-main">
<el-collapse accordion> <el-collapse accordion>
<el-collapse-item :name="ins" v-for="(item, ins) in warnGroupList" :key="item.cameraId[0]"> <el-collapse-item :name="ins" v-for="(item, ins) in warnGroupList" :key="item.cameraId[0]">
<template #title> <template #title>
<div class="collapse-title" @click.stop=""> <div class="collapse-title" @click.stop="">
<div class="titlemodel">{{ item.name }} {{ item.cameraId[0] }}</div>
<div class="titlemodel">
<div style="width: 220px; text-align: left">{{ item.name }} {{ item.cameraId[0] }}</div>
<div style="margin-left: 20px">
<el-button @click="pushPerson(FormOptEnum.VideoPushPerson, item)" type="primary" size="small">设置推送人</el-button>
</div>
</div>
<div class="btns"> <div class="btns">
<el-switch v-model="item.state" @change="stateChange" /> <el-switch v-model="item.state" @change="stateChange" />
</div> </div>
@@ -29,12 +45,12 @@
</div> </div>
</div> --> </div> -->
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="6" v-for="(v, index) in item.subset" :key="v.code">
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="6" v-for="(v, index) in item.subset" :key="v.code">
<div class="contentinfo"> <div class="contentinfo">
<div class="modellabel">{{ v.name }}</div> <div class="modellabel">{{ v.name }}</div>


<div class="btns"> <div class="btns">
<el-switch v-model="v.state" @change="stateChange" />
<el-switch :disabled="item.state == false" v-model="v.state" @change="stateChange" />
</div> </div>
</div> </div>
</el-col> </el-col>
@@ -43,6 +59,8 @@
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</div> </div>
<!-- 人员选择 -->
<userForm ref="userFormRef" />
</div> </div>
</template> </template>


@@ -51,12 +69,14 @@ import { ref, watch, provide, onMounted, unref, computed, reactive } from "vue";
import TreeFilter from "@/components/TreeFilter/index.vue"; import TreeFilter from "@/components/TreeFilter/index.vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { abilityApi, userManageClassManageApi, monitorLIVEApi } from "@/api"; import { abilityApi, userManageClassManageApi, monitorLIVEApi } from "@/api";
import { FormOptEnum, SysDictEnum, MenuTypeDictEnum } from "@/enums";
import userForm from "./components/userForm.vue";


const value = ref(true); const value = ref(true);
onMounted(() => { onMounted(() => {
// 在这里执行其他需要在组件挂载后运行的代码 // 在这里执行其他需要在组件挂载后运行的代码
getwarnGroup(); getwarnGroup();
getVideoList()
getVideoList('')
}); });
const treeFilter = ref<InstanceType<typeof TreeFilter> | null>(null); const treeFilter = ref<InstanceType<typeof TreeFilter> | null>(null);
const treeFilters = ref<InstanceType<typeof TreeFilter> | null>(null); const treeFilters = ref<InstanceType<typeof TreeFilter> | null>(null);
@@ -66,12 +86,13 @@ function changeGroup(val: number | string) {
// proTable.value!.pageable.pageNum = 1; // proTable.value!.pageable.pageNum = 1;
// proTable.value!.searchParam.personSetId = val; // proTable.value!.searchParam.personSetId = val;
// proTable.value!.search(); // proTable.value!.search();
// getVideoList(val.id)
getVideoList(val)
} }
const videoList = ref<any>(); const videoList = ref<any>();
function getVideoList() {
function getVideoList(id:any) {
console.log(id,11)
setTimeout(async () => { setTimeout(async () => {
await monitorLIVEApi.list({ pageNum: 1, pageSize: 1000 }).then(res => {
await monitorLIVEApi.list({ pageNum: 1, pageSize: 1000, groupId:id }).then(res => {
videoList.value = res.data.list; videoList.value = res.data.list;
}); });
}); });
@@ -99,6 +120,10 @@ function getwarnGroup() {
}); });
}); });
} }
const userFormRef = ref<InstanceType<typeof Form> | null>(null);
function pushPerson(opt: FormOptEnum, record: {} | SysOrg.SysOrgInfo = {}) {
userFormRef.value?.onOpen({ opt: opt, record: record, successful: getwarnGroup });
}
// 开关 // 开关
function stateChange() { function stateChange() {
let params: string = JSON.stringify(warnGroupList.value); let params: string = JSON.stringify(warnGroupList.value);
@@ -137,6 +162,8 @@ function stateChange() {
justify-content: space-between; justify-content: space-between;
order: 1; order: 1;
.titlemodel { .titlemodel {
display: flex;
align-items: center;
margin-right: 40px; margin-right: 40px;
font-size: 18px; font-size: 18px;
} }


Loading…
Cancel
Save