feat:标书需求增补

This commit is contained in:
dzc committed 2026-04-02 19:18:31 +08:00
1 parent 9d65f30bd4
commit e4628ca19d
8 files changed
+388 -43

No files matched your search

+14 -1
View File
@@ -4,7 +4,8 @@
children: 'deviceChannelList',
}" node-key="treeValue" v-model="state.selectId" :placeholder="props.placeholder" :clearable="props.clearable"
:loading="state.loading" :data="state.options" :render-after-expand="false" show-checkbox multiple
style="width: 100%" filterable default-expand-all @visible-change="(e: boolean) => e && getOptions()">
style="width: 100%" filterable :filter-node-method="filterNode" default-expand-all
@visible-change="(e: boolean) => e && getOptions()">
<template #default="{ data, node }">
<div v-if="node.level == 1" class="flex items-center gap-2">
<el-tag size="small" effect="dark" color="var(--el-color-primary)">硬盘录像机</el-tag>
@@ -66,6 +67,18 @@ watch(
{ immediate: true },
)
const filterNode = (value: string, data: any, node: any) => {
const kw = (value ?? '').toString().trim().toLowerCase()
if (!kw) return true
const selfDeviceName = (data?.deviceName ?? '').toString().toLowerCase()
const selfChannelName = (data?.channelName ?? '').toString().toLowerCase()
const parentDeviceName = (node?.parent?.data?.deviceName ?? '').toString().toLowerCase()
if (selfDeviceName && selfDeviceName.includes(kw)) return true
if (selfChannelName && selfChannelName.includes(kw)) return true
if (parentDeviceName && parentDeviceName.includes(kw)) return true
return false
}
async function getOptions() {
try {
state.loading = true
+214 -21
View File
@@ -1,26 +1,158 @@
<template>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="180px"
v-loading="state.loading">
<!-- **************************** start 翻墙配置 start **************************** -->
<el-divider class="my-12">翻墙配置</el-divider>
<el-form-item prop="armyCarSetting.armyCarPrefixs">
<!-- **************************** start 出入人闸配置 start **************************** -->
<el-divider class="my-12">出入人闸配置</el-divider>
<el-form-item prop="cameraLocation.personEnterChannels">
<template #label>
<div class="flex items-center gap-1">
<span>报警类型</span>
<span>入口人闸摄像头配置</span>
</div>
</template>
<dict-select v-model="form.overTheWallSetting.alarmTypeList" :options="alarm_type" multiple filterable
placeholder="请选择报警类型" />
<select-tree-channel v-model="form.cameraLocation.personEnterChannels" placeholder="请选择入口人闸摄像头配置" />
</el-form-item>
<!-- **************************** end 翻墙配置 end **************************** -->
<el-form-item prop="cameraLocation.personExitChannels">
<template #label>
<div class="flex items-center gap-1">
<span>出口人闸摄像头配置</span>
</div>
</template>
<select-tree-channel v-model="form.cameraLocation.personExitChannels" placeholder="请选择出口人闸摄像头配置" />
</el-form-item>
<!-- **************************** end 出入人闸配置 end **************************** -->
<!-- **************************** start 夜晚出入营区 start **************************** -->
<el-divider class="my-12">夜晚出入营区</el-divider>
<el-form-item prop="personNightCamp.alarmTime">
<template #label>
<div class="flex items-center gap-1">
<span>夜晚出入时间</span>
</div>
</template>
<el-time-picker format="HH:mm" value-format="HH:mm" v-model="form.personNightCamp.alarmTime" is-range
placeholder="请选择夜晚出入时间" />
</el-form-item>
<el-form-item prop="personNightCamp.cameraChannels">
<template #label>
<div class="flex items-center gap-1">
<span>摄像头</span>
</div>
</template>
<select-tree-channel v-model="form.personNightCamp.cameraChannels" placeholder="请选择摄像头" />
</el-form-item>
<!-- **************************** end 夜晚出入营区 end **************************** -->
<!-- **************************** start 夜晚出入办公楼 start **************************** -->
<el-divider class="my-12">夜晚出入办公楼</el-divider>
<el-form-item prop="personNightOffice.alarmTime">
<template #label>
<div class="flex items-center gap-1">
<span>夜晚出入时间</span>
</div>
</template>
<el-time-picker format="HH:mm" value-format="HH:mm" v-model="form.personNightOffice.alarmTime" is-range
placeholder="请选择夜晚出入时间" />
</el-form-item>
<el-form-item prop="personNightOffice.cameraChannels">
<template #label>
<div class="flex items-center gap-1">
<span>摄像头</span>
</div>
</template>
<select-tree-channel v-model="form.personNightOffice.cameraChannels" placeholder="请选择摄像头" />
</el-form-item>
<!-- **************************** end 夜晚出入办公楼 end **************************** -->
<!-- **************************** start 打卡 start **************************** -->
<el-divider class="my-12">打卡配置</el-divider>
<el-form-item prop="personDk.forenoon">
<template #label>
<div class="flex items-center gap-1">
<span>打卡时间(上午)</span>
</div>
</template>
<el-time-picker format="HH:mm" value-format="HH:mm" v-model="form.personDk.forenoon" is-range
placeholder="请选择打卡时间(上午)" />
</el-form-item>
<el-form-item prop="personDk.afternoon">
<template #label>
<div class="flex items-center gap-1">
<span>打卡时间(下午)</span>
</div>
</template>
<el-time-picker format="HH:mm" value-format="HH:mm" v-model="form.personDk.afternoon" is-range
placeholder="请选择打卡时间(下午)" />
</el-form-item>
<el-form-item prop="personDk.cameraChannels">
<template #label>
<div class="flex items-center gap-1">
<span>门口人闸摄像头</span>
</div>
</template>
<select-tree-channel v-model="form.personDk.cameraChannels" placeholder="请选择摄像头" />
</el-form-item>
<el-form-item prop="personDk.mainFloorCameraChannels">
<template #label>
<div class="flex items-center gap-1">
<span>主楼摄像头</span>
</div>
</template>
<select-tree-channel v-model="form.personDk.mainFloorCameraChannels" placeholder="请选择摄像头" />
</el-form-item>
<el-form-item prop="personDk.deptCodes">
<template #label>
<div class="flex items-center gap-1">
<span>部门</span>
</div>
</template>
<select-tree-dept v-model="form.personDk.deptCodes" placeholder="请选择部门" />
</el-form-item>
<!-- **************************** end 打卡 end **************************** -->
<!-- **************************** start 考勤 start **************************** -->
<el-divider class="my-12">考勤配置</el-divider>
<el-form-item prop="personKq.forenoon">
<template #label>
<div class="flex items-center gap-1">
<span>考勤时间(上午)</span>
</div>
</template>
<el-time-picker format="HH:mm" value-format="HH:mm" v-model="form.personKq.forenoon" is-range
placeholder="请选择考勤时间(上午)" />
</el-form-item>
<el-form-item prop="personKq.afternoon">
<template #label>
<div class="flex items-center gap-1">
<span>考勤时间(下午)</span>
</div>
</template>
<el-time-picker format="HH:mm" value-format="HH:mm" v-model="form.personKq.afternoon" is-range
placeholder="请选择考勤时间(下午)" />
</el-form-item>
<el-form-item prop="personKq.cameraChannels">
<template #label>
<div class="flex items-center gap-1">
<span>摄像头</span>
</div>
</template>
<select-tree-channel v-model="form.personKq.cameraChannels" placeholder="请选择摄像头" />
</el-form-item>
<el-form-item prop="personKq.deptCodes">
<template #label>
<div class="flex items-center gap-1">
<span>部门</span>
</div>
</template>
<select-tree-dept v-model="form.personKq.deptCodes" placeholder="请选择部门" />
</el-form-item>
<!-- **************************** end 考勤 end **************************** -->
</el-form>
</template>
<script setup lang="ts" name="over-the-wall-setting">
<script setup lang="ts" name="doorSetting">
import { useMessage } from "/@/hooks/message"
import { useDict } from '/@/hooks/dict';
import * as ComDhSettingApi from "/@/api/com/comDhSetting";
const dataFormRef = ref();
@@ -29,20 +161,52 @@ const state = reactive<any>({
loading: false,
})
const { alarm_type } = useDict("alarm_type")
// 提交表单数据
const form = reactive<any>({
// 翻墙配置
overTheWallSetting: {
// 报警类型
alarmTypeList: [],
// 出入口摄像头配置
cameraLocation: {
// 人闸入口摄像头配置
personEnterChannels: [],
// 人闸出口摄像头配置
personExitChannels: [],
},
// 人员晚上出入营区
personNightCamp: {
alarmTime: [],
cameraChannels: [],
},
// 人员晚上出入办公楼
personNightOffice: {
alarmTime: [],
cameraChannels: [],
},
// 人员打卡配置
personDk: {
forenoon: [],
afternoon: [],
cameraChannels: [],
deptCodes: [],
},
// 人员考勤配置
personKq: {
forenoon: [],
afternoon: [],
cameraChannels: [],
deptCodes: [],
},
})
const dataRules = ref({
// 翻墙配置
"overTheWallSetting.alarmTypeList": [{ required: true, message: '报警类型不能为空', trigger: 'blur' }],
// 人员晚上出入营区
"personNightCamp.alarmTime": [{ required: true, message: '夜晚出入时间不能为空', trigger: 'blur' }],
// 人员晚上出入办公楼
"personNightOffice.alarmTime": [{ required: true, message: '夜晚出入时间不能为空', trigger: 'blur' }],
// 人员打卡配置
"personDk.forenoon": [{ required: true, message: '打卡时间(上午)不能为空', trigger: 'blur' }],
"personDk.afternoon": [{ required: true, message: '打卡时间(下午)不能为空', trigger: 'blur' }],
// 人员考勤配置
"personKq.forenoon": [{ required: true, message: '考勤时间(上午)不能为空', trigger: 'blur' }],
"personKq.afternoon": [{ required: true, message: '考勤时间(下午)不能为空', trigger: 'blur' }],
})
onMounted(() => {
@@ -53,9 +217,38 @@ async function getSetting() {
state.loading = true
try {
const { data } = await ComDhSettingApi.getObj()
if (!data.overTheWallSetting) {
data.overTheWallSetting = {
alarmTypeList: [],
if (!data.cameraLocation) {
data.cameraLocation = {
personEnterChannels: [],
personExitChannels: [],
}
}
if (!data.personNightCamp) {
data.personNightCamp = {
alarmTime: [],
cameraChannels: [],
}
}
if (!data.personNightOffice) {
data.personNightOffice = {
alarmTime: [],
cameraChannels: [],
}
}
if (!data.personDk) {
data.personDk = {
forenoon: [],
afternoon: [],
cameraChannels: [],
deptCodes: [],
}
}
if (!data.personKq) {
data.personKq = {
forenoon: [],
afternoon: [],
cameraChannels: [],
deptCodes: [],
}
}
if (data) {
+148 -7
View File
@@ -2,7 +2,6 @@
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="180px"
v-loading="state.loading">
<el-divider class="mb-12">大屏配置</el-divider>
<el-form-item prop="adminUrl">
<template #label>
<div class="flex items-center gap-1">
@@ -16,7 +15,6 @@
</template>
<el-input v-model="form.adminUrl" placeholder="请输入后台地址" />
</el-form-item>
<el-form-item prop="panelUrl">
<template #label>
<div class="flex items-center gap-1">
@@ -36,7 +34,6 @@
</template>
</el-input>
</el-form-item>
<el-form-item prop="panelClickCollectEnable">
<template #label>
<div class="flex items-center gap-1">
@@ -51,7 +48,6 @@
<el-switch v-model="form.panelClickCollectEnable" active-text="开启" inactive-text="关闭" active-value="1"
inactive-value="0" />
</el-form-item>
<el-form-item prop="panelClickCollectEnable">
<template #label>
<div class="flex items-center gap-1">
@@ -68,12 +64,90 @@
<el-radio label="CAMERA" size="large">摄像头</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="是否使用插件模式播放" prop="panelPluginVideoEnable">
<el-switch v-model="form.panelPluginVideoEnable" active-text="开启" inactive-text="关闭" active-value="1"
inactive-value="0" />
</el-form-item>
<el-divider class="mb-12">南门左侧人闸</el-divider>
<el-form-item label="编号" prop="nmLeftDoorGateSetting.uniqueCode">
<el-input v-model="form.nmLeftDoorGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="nmLeftDoorGateSetting.enterChannelList">
<select-tree-channel v-model="form.nmLeftDoorGateSetting.enterChannelList" placeholder="请选择入口人闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="nmLeftDoorGateSetting.exitChannelList">
<select-tree-channel v-model="form.nmLeftDoorGateSetting.exitChannelList" placeholder="请选择入口人闸摄像头配置" />
</el-form-item>
<el-divider class="mb-12">南门右侧人闸</el-divider>
<el-form-item label="编号" prop="nmRightDoorGateSetting.uniqueCode">
<el-input v-model="form.nmRightDoorGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="nmRightDoorGateSetting.enterChannelList">
<select-tree-channel v-model="form.nmRightDoorGateSetting.enterChannelList" placeholder="请选择入口人闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="nmRightDoorGateSetting.exitChannelList">
<select-tree-channel v-model="form.nmRightDoorGateSetting.exitChannelList" placeholder="请选择出口人闸摄像头配置" />
</el-form-item>
<el-divider class="mb-12">南门车闸</el-divider>
<el-form-item label="编号" prop="nmCarGateSetting.uniqueCode">
<el-input v-model="form.nmCarGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="nmCarGateSetting.enterChannelList">
<select-tree-channel v-model="form.nmCarGateSetting.enterChannelList" placeholder="请选择入口车闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="nmCarGateSetting.exitChannelList">
<select-tree-channel v-model="form.nmCarGateSetting.exitChannelList" placeholder="请选择出口车闸摄像头配置" />
</el-form-item>
<el-divider class="mb-12">北门左侧人闸</el-divider>
<el-form-item label="编号" prop="bmLeftDoorGateSetting.uniqueCode">
<el-input v-model="form.bmLeftDoorGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="bmLeftDoorGateSetting.enterChannelList">
<select-tree-channel v-model="form.bmLeftDoorGateSetting.enterChannelList" placeholder="请选择入口人闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="bmLeftDoorGateSetting.exitChannelList">
<select-tree-channel v-model="form.bmLeftDoorGateSetting.exitChannelList" placeholder="请选择出口人闸摄像头配置" />
</el-form-item>
<el-divider class="mb-12">北门车闸配置</el-divider>
<el-form-item label="编号" prop="bmCarGateSetting.uniqueCode">
<el-input v-model="form.bmCarGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="bmCarGateSetting.enterChannelList">
<select-tree-channel v-model="form.bmCarGateSetting.enterChannelList" placeholder="请选择入口车闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="bmCarGateSetting.exitChannelList">
<select-tree-channel v-model="form.bmCarGateSetting.exitChannelList" placeholder="请选择出口车闸摄像头配置" />
</el-form-item>
<el-divider class="mb-12">东门车闸配置</el-divider>
<el-form-item label="编号" prop="dmCarGateSetting.uniqueCode">
<el-input v-model="form.dmCarGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="dmCarGateSetting.enterChannelList">
<select-tree-channel v-model="form.dmCarGateSetting.enterChannelList" placeholder="请选择入口车闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="dmCarGateSetting.exitChannelList">
<select-tree-channel v-model="form.dmCarGateSetting.exitChannelList" placeholder="请选择出口车闸摄像头配置" />
</el-form-item>
<el-divider class="mb-12">机关楼前门禁</el-divider>
<el-form-item label="编号" prop="gglFrontDoorGateSetting.uniqueCode">
<el-input v-model="form.gglFrontDoorGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="gglFrontDoorGateSetting.enterChannelList">
<select-tree-channel v-model="form.gglFrontDoorGateSetting.enterChannelList" placeholder="请选择入口车闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="gglFrontDoorGateSetting.exitChannelList">
<select-tree-channel v-model="form.gglFrontDoorGateSetting.exitChannelList" placeholder="请选择出口车闸摄像头配置" />
</el-form-item>
<el-divider class="mb-12">机关楼后门禁</el-divider>
<el-form-item label="编号" prop="gglBehindDoorGateSetting.uniqueCode">
<el-input v-model="form.gglBehindDoorGateSetting.uniqueCode" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="进口设备" prop="gglBehindDoorGateSetting.enterChannelList">
<select-tree-channel v-model="form.gglBehindDoorGateSetting.enterChannelList" placeholder="请选择入口车闸摄像头配置" />
</el-form-item>
<el-form-item label="出口设备" prop="gglBehindDoorGateSetting.exitChannelList">
<select-tree-channel v-model="form.gglBehindDoorGateSetting.exitChannelList" placeholder="请选择出口车闸摄像头配置" />
</el-form-item>
</el-form>
</template>
@@ -104,6 +178,54 @@ const form = reactive<any>({
panelCollectEnableType: "ROOM_NUM",
// 是否使用插件模式播放
panelPluginVideoEnable: "0",
// 南门左侧人闸设备配置
nmLeftDoorGateSetting: {
uniqueCode: "",
enterChannelList: [],
exitChannelList: [],
},
// 南门右侧人闸设备配置
nmRightDoorGateSetting: {
uniqueCode: "",
enterChannelList: [],
exitChannelList: [],
},
// 南门车闸配置
nmCarGateSetting: {
uniqueCode: "",
enterChannelList: [],
exitChannelList: [],
},
// 北门左侧人闸设备配置
bmLeftDoorGateSetting: {
uniqueCode: "",
enterChannelList: [],
exitChannelList: [],
},
// 北门车闸配置
bmCarGateSetting: {
uniqueCode: "",
enterChannelList: [],
exitChannelList: [],
},
// 东门车闸配置
dmCarGateSetting: {
uniqueCode: "",
enterChannelList: "",
exitChannelList: "",
},
// 机关楼前门禁配置
gglFrontDoorGateSetting: {
uniqueCode: "",
enterChannelList: [],
exitChannelList: [],
},
// 机关楼后门禁配置
gglBehindDoorGateSetting: {
uniqueCode: "",
enterChannelList: [],
exitChannelList: [],
},
})
const dataRules = ref({
@@ -121,7 +243,26 @@ async function getSetting() {
try {
const { data } = await ComDhSettingApi.getObj()
if (data) {
Object.assign(form, data)
const gate = (v: any) => {
const d = v || {}
return {
uniqueCode: d.uniqueCode ?? "",
enterChannelList: d.enterChannelList ?? [],
exitChannelList: d.exitChannelList ?? [],
}
}
const normalized = {
...data,
nmLeftDoorGateSetting: gate(data?.nmLeftDoorGateSetting),
nmRightDoorGateSetting: gate(data?.nmRightDoorGateSetting),
nmCarGateSetting: gate(data?.nmCarGateSetting),
bmLeftDoorGateSetting: gate(data?.bmLeftDoorGateSetting),
bmCarGateSetting: gate(data?.bmCarGateSetting),
dmCarGateSetting: gate(data?.dmCarGateSetting),
gglFrontDoorGateSetting: gate(data?.gglFrontDoorGateSetting),
gglBehindDoorGateSetting: gate(data?.gglBehindDoorGateSetting),
}
Object.assign(form, normalized)
}
} catch (err: any) {
console.error(err);
@@ -40,9 +40,9 @@
<el-table-column prop="channelName" width="160" label="通道名" />
<el-table-column prop="deviceIp" width="120" label="ip" />
<el-table-column prop="devicePort" width="120" label="端口" />
<el-table-column prop="devicePort" width="120" label="状态">
<el-table-column prop="deviceIsOnline" width="120" label="状态">
<template #default="{ row }">
<tag-online :isOnline="row.isOnline == 1" />
<tag-online :isOnline="row.deviceIsOnline == 1" />
</template>
</el-table-column>
</el-table-column>
+2 -2
View File
@@ -94,9 +94,9 @@
<el-table-column label="抓拍相机">
<el-table-column prop="devId" min-width="100" label="设备编码" />
<el-table-column prop="devName" min-width="100" label="设备名称" />
<el-table-column prop="devChnName" min-width="100" label="通道名称" />
<el-table-column prop="devName" min-width="100" label="设备名称" show-overflow-tooltip />
<el-table-column prop="devChnId" min-width="150" label="通道编码" />
<el-table-column prop="devChnName" min-width="100" label="通道名称" show-overflow-tooltip />
</el-table-column>
<el-table-column label="抓拍图片">
+1 -1
View File
@@ -67,7 +67,7 @@ const form = reactive({ ...defaultForm });
// 定义校验规则
const dataRules = ref({
name: [{ required: true, message: '分组名称不能为空', trigger: 'blur' }],
panelViewCodes: [{ required: true, message: '类型不能为空', trigger: 'change' }],
// panelViewCodes: [{ required: true, message: '类型不能为空', trigger: 'change' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
})
+2 -2
View File
@@ -49,7 +49,7 @@
<dict-tag :options="device_group_type" :value="row.bizType" />
</template>
</el-table-column>
<el-table-column prop="panelViewCodes" width="450" label="大屏预览分组">
<el-table-column prop="panelViewCodes" width="600" label="大屏预览分组">
<template #default="{ row }">
<div class="flex items-center gap-2">
<dict-tag v-for="v in row.panelViewCodes?.split(',')" :options="panel_type" :value="v" />
@@ -67,7 +67,7 @@
@click="formDialogRef.openDialog(row.id)">
编辑
</el-button>
<el-button v-if="row.bizType != 1" icon="delete" text type="primary" v-auth="'device_deviceGroup_del'"
<el-button icon="delete" text type="primary" v-auth="'device_deviceGroup_del'"
@click="handleDelete([row.id])">
删除
</el-button>
+5 -7
View File
@@ -118,13 +118,11 @@
<dict-tag :options="dh_door_open_type" :value="row.openType" />
</template>
</el-table-column>
<el-table-column label="设备" min-width="280">
<template #default="{ row }">
<div class="flex items-center justify-start">
<span>{{ row.deviceName }}</span>
<span v-if="row.channelName">{{ row.channelName }}</span>
</div>
</template>
<el-table-column label="抓拍相机">
<el-table-column prop="deviceCode" min-width="100" label="设备编码" />
<el-table-column prop="deviceName" min-width="100" label="设备名称" show-overflow-tooltip />
<el-table-column prop="channelCode" min-width="150" label="通道编码" />
<el-table-column prop="channelName" min-width="100" label="通道名称" show-overflow-tooltip />
</el-table-column>
<el-table-column label="抓图图片" min-width="100">
<template #default="{ row }">