+
+
diff --git a/apps/web-antd/src/views/screen/monitor/map/Map.vue b/apps/web-antd/src/views/screen/monitor/map/Map.vue
new file mode 100644
index 00000000..f56abc0f
--- /dev/null
+++ b/apps/web-antd/src/views/screen/monitor/map/Map.vue
@@ -0,0 +1,232 @@
+
+
+
- 在线数量
+
+
+ 4
+ 7
+ 3
+ 个
南川区综合服务中心数智管理平台监控大屏
-
-
+ {{ weekDay }}
- 晴
- 40℃
-
-
-
+
+ 
- 退出
+
+
+
+
+
+
+
+
+ 监控编号 | +监控位置 | +监控范围 | +监控情况 | +
---|---|---|---|
0625142512 | +东区大门 | +右侧 | +正常 | +
0625342512 | +东区大门 | +左侧 | +正常 | +
0625142513 | +东区大门 | +正前方 | +正常 | +
0625142912 | +东区大门 | +马路 | +异常 | +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+ 已处理
+ 8
+ 19.1
+
+
+ 未处理
+ 12
+ 19.1
+
+
+
+ 今日报警
+ 12
+ 19.1
+
+
完成率
+ 66%
+ 19.1
+
-
+
-
+
-
-
-
-
-
- 在线数量
-
-
- 4
- 7
- 3
- 个
-
-
-
-
-
-
-
- 监控编号 | -监控位置 | -监控范围 | -监控情况 | -
---|---|---|---|
0625142512 | -东区大门 | -右侧 | -正常 | -
0625342512 | -东区大门 | -左侧 | -正常 | -
0625142513 | -东区大门 | -正前方 | -正常 | -
0625142912 | -东区大门 | -马路 | -异常 | -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 
-
-
- 
-
-
-
-
- 
-
-
- 
-
-
-
-
- 
-
-
- 
-
+
-
-
-
-
-
-
-
-
-
- 已处理
- 8
- 19.1
-
-
- 未处理
- 12
- 19.1
-
-
-
-
- 今日报警
- 12
- 19.1
-
-
- 完成率
- 66%
- 19.1
-
-
-
-
-
-
-
- 报警时间 | -报警位置 | -报警内容 | -处理情况 | -
---|---|---|---|
06-25 14:25:12 | -东区大门 | -门禁异常 | -已处理 | -
06-25 14:25:12 | -东区大门 | -门禁异常 | -已处理 | -
06-25 14:25:12 | -东区大门 | -门禁异常 | -已处理 | -
06-25 14:25:12 | -东区大门 | -门禁异常 | -未处理 | -
-
-
-
-
-
-
-
-
-
- 
-
- 设备总数
- 650
-
-
-
-
-
- 
-
- 设备在线数
- 632
-
-
-
-
-
- 
-
- 设备离线数
- 18
-
+
+
+
+
+
+ 报警时间 | +报警位置 | +报警内容 | +处理情况 | +
---|---|---|---|
06-25 14:25:12 | +东区大门 | +门禁异常 | +已处理 | +
06-25 14:25:12 | +东区大门 | +门禁异常 | +已处理 | +
06-25 14:25:12 | +东区大门 | +门禁异常 | +已处理 | +
06-25 14:25:12 | +东区大门 | +门禁异常 | +未处理 | +
+
+
+
+
+
+
+
+
+ 
+
+ 设备总数
+ 650
+
+
+
+
+
+ 
+
+ 设备在线数
+ 632
+
+
+
+
+
+ 
+
+ 设备离线数
+ 18
+
+
+
+
+
diff --git a/apps/web-antd/src/views/screen/monitor/map/constants.js b/apps/web-antd/src/views/screen/monitor/map/constants.js
new file mode 100644
index 00000000..cca3ec5a
--- /dev/null
+++ b/apps/web-antd/src/views/screen/monitor/map/constants.js
@@ -0,0 +1,16 @@
+import camera from "#/assets/map/camear.png";
+
+export const MapDefaultData = {
+ center: [107.089,29.1714],
+ zoom: 21,
+ icons: {camera}
+};
+
+
+export const icons = {
+ camera: new BMap.Icon(MapDefaultData.icons.camera, new BMap.Size(23, 34), {
+ offset: new BMap.Size(12, 30),
+ textColor: '#fff',
+ zIndex: "100"
+ })
+}
diff --git a/apps/web-antd/src/views/screen/monitor/map/map.scss b/apps/web-antd/src/views/screen/monitor/map/map.scss
new file mode 100644
index 00000000..1174a593
--- /dev/null
+++ b/apps/web-antd/src/views/screen/monitor/map/map.scss
@@ -0,0 +1,94 @@
+.vmap {
+ position: relative;
+ width: 100%;
+ height: 100%;
+
+ .BMap_pop > div {
+ background: transparent !important;
+ border: 0 !important;
+ }
+
+ .BMap_pop > div:nth-child(n) {
+ display: none
+ }
+
+ .BMap_pop > div:nth-child(9) {
+ display: block
+ }
+
+ .BMap_pop > img {
+ width: 0 !important;
+ height: 0 !important;
+ }
+
+ #map {
+ width: 100%;
+ height: 100%;
+
+ .anchorBL {
+ display: none !important;
+ }
+
+ .close {
+ position: absolute;
+ right: 12px;
+ top: 5px;
+ font-size: 18px;
+ cursor: pointer;
+ border: 1px solid #409eff;
+ color: #409eff;
+ padding: 2px 5px;
+ text-align: center;
+ z-index: 100;
+ }
+
+ .wrap-title {
+ margin-top: 16px;
+ font-size: 16px;
+ color: white;
+ position: absolute;
+ height: 30px;
+ width: 100%;
+ line-height: 30px;
+ left: 20px;
+ font-weight: bold;
+ }
+
+ .video-wrap {
+ width: 530px !important;
+ height: 360px;
+ background: url("/src/assets/map/video-bg.png") no-repeat;
+ background-size: 100% 100%;
+
+ .wrap-content {
+ padding: 15px 10px 10px 10px;
+ height: 75%;
+ display: flex;
+
+ .content-left {
+ height: 100%;
+ width: 100%;
+ }
+
+ img {
+ width: 100%;
+ height: 111%;
+ }
+
+ video {
+ width: 100%;
+ height: 100%;
+ }
+
+ .content-right {
+ margin-left: 15px;
+ padding-top: 10px;
+ }
+
+ }
+
+
+ }
+ }
+
+}
diff --git a/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue b/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue
index 97997178..5ac53c85 100644
--- a/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue
+++ b/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue
@@ -2,21 +2,14 @@
import { onMounted, ref, toRaw } from 'vue';
import { SyncOutlined } from '@ant-design/icons-vue';
import { InputSearch, message, Skeleton, Tree } from 'ant-design-vue';
-import { queryTree } from '#/api/sis/accessControl';
+import { queryTree, remoteOpenDoor } from '#/api/sis/accessControl';
import type { TreeNode } from '#/api/common';
defineOptions({ inheritAttrs: false });
withDefaults(defineProps<{ showSearch?: boolean }>(), { showSearch: true });
-const emit = defineEmits<{
- checked: [];
- /**
- * 点击节点的事件
- */
- reload: [];
- select: [];
-}>();
+const emit = defineEmits(['checked', 'reload', 'select']);
const searchValue = defineModel('searchValue', {
type: String,
@@ -39,6 +32,7 @@ async function loadChannelTree() {
function handleNode(nodes: any[], level: number) {
nodes.forEach((node) => {
+ node.key = node.id;
if (node.level < level) {
node.disabled = true;
}
@@ -57,13 +51,14 @@ function open() {
const acArr = checkNodeData();
if (acArr) {
console.log(acArr);
+ remoteOpenDoor({ acIds: acArr, type: 0 });
}
}
function close() {
const acArr = checkNodeData();
if (acArr) {
- console.log(acArr);
+ remoteOpenDoor({ acIds: acArr, type: 1 });
}
}
@@ -71,6 +66,7 @@ function alwaysOpen() {
const acArr = checkNodeData();
if (acArr) {
console.log(acArr);
+ remoteOpenDoor({ acIds: acArr, type: 2 });
}
}
@@ -78,6 +74,7 @@ function reSet() {
const acArr = checkNodeData();
if (acArr) {
console.log(acArr);
+ remoteOpenDoor({ acIds: acArr, type: 4 });
}
}
@@ -92,7 +89,7 @@ function checkNodeData() {
arr.forEach((item) => {
const node: any = checkData[item];
if (node.level == 5) {
- acArr.push(node);
+ acArr.push(node.id);
}
});
if (!acArr || acArr.length === 0) {
@@ -104,7 +101,13 @@ function checkNodeData() {
const checkData: any = {};
+/**
+ * 树选中时间
+ * @param _keys 当前选中的节点key
+ * @param nodes 当前选中的节点
+ */
function onTreeCheck(_keys: any, nodes: any) {
+ // nodes 为当前当前选中的节点
const { checked, checkedNodes } = nodes;
// 找到需要播放的视频节点
checkedNodes.forEach((node: any) => {
@@ -116,8 +119,7 @@ function onTreeCheck(_keys: any, nodes: any) {
delete checkData[id];
}
});
- const data = toRaw(checkedNodes);
- emit('checked', data);
+ emit('checked', _keys, nodes);
}
onMounted(loadChannelTree);
diff --git a/apps/web-antd/src/views/sis/acAdmin/index.vue b/apps/web-antd/src/views/sis/acAdmin/index.vue
index 47fcb088..8d6febaf 100644
--- a/apps/web-antd/src/views/sis/acAdmin/index.vue
+++ b/apps/web-antd/src/views/sis/acAdmin/index.vue
@@ -1,7 +1,7 @@
-
+
import DpTree from './dp-tree.vue';
import { Page } from '@vben/common-ui';
-import { ref } from 'vue';
-import mpegts from "mpegts.js";
-import {addStreamProxy} from "#/api/sis/stream";
-import {message} from "ant-design-vue";
+import { onMounted, onUnmounted, ref, toRaw } from 'vue';
+import mpegts from 'mpegts.js';
+import { addFFmpegStreamProxy, addStreamProxy } from '#/api/sis/stream';
+import { message } from 'ant-design-vue';
+import { checkHEVCSupport } from '#/utils/video';
+import type { AddStreamProxyResult } from '#/api/sis/stream/model';
/**
* 屏幕播放器数量
*/
const selected = 'selected';
-const playerNum = ref(4);
+const playerNum = ref(1);
/**
* 屏幕播放器样式
*/
const playerStyle = ref({
- width: '50%',
- height: '50%',
+ width: '100%',
+ height: '100%',
});
const currentSelectPlayerIndex = ref(-1);
@@ -61,13 +63,111 @@ const setItemRef = (el: any) => {
}
};
-function onNodeChecked(nodes: any[]) {
- console.log(nodes);
+/**
+ * 处理带有子节点的数据
+ * @param node
+ * @param newNode
+ */
+function handleParentNoe(node: any, newNode: any[] = []) {
+ node.forEach((item: any) => {
+ if (item.level === 6) {
+ newNode.push(toRaw(item.data));
+ }
+ if (item.children && item.children.length >= 1) {
+ handleParentNoe(item.children, newNode);
+ }
+ });
+}
+
+/**
+ * 节点选中时间处理
+ * @param _val 选中节点id
+ * @param checked 是否选中
+ * @param node 节点数据
+ */
+function onNodeChecked(
+ _val: any,
+ { checked, node }: { checked: boolean; node: any },
+) {
+ // 此次操作需要新增或者删除节点
+ let checkNode: any = [];
+ handleParentNoe([node], checkNode);
+ // 新增
+ if (checked) {
+ /**
+ * 如果当前页面有选择播放未知,并且播放视频只有一个,则播放到制定位置
+ */
+ if (currentSelectPlayerIndex.value !== -1 && checkNode.length == 1) {
+ doPlayer(checkNode[0], currentSelectPlayerIndex.value - 1);
+ }
+ // 批量播放 currentSelectPlayerIndex 将不再生效
+ else {
+ // 如果此次播放数量小于当前播能播放
+ const freeArr: number[] = []; // 空闲播放器数量
+ for (let i = 0; i < playerNum.value; i++) {
+ const playerData = playerList[i];
+ if (!playerData) {
+ freeArr.push(i);
+ }
+ }
+ // 要播放的视频数量,小于等于空闲播放器数量,则填充空闲即可
+ if (checkNode.length <= freeArr.length) {
+ for (let j = 0; j < checkNode.length; j++) {
+ doPlayer(checkNode[j], freeArr[j]);
+ }
+ }
+ // 直接覆盖原有的播放视频
+ else {
+ for (let i = 0; i < playerNum.value; i++) {
+ doPlayer(checkNode[i], i);
+ }
+ }
+ }
+ }
+ // 删除
+ else {
+ checkNode.forEach((item: any) => {
+ for (let i = 0; i < playerNum.value; i++) {
+ const player = playerList[i];
+ if (player && player.data.id === item.id) {
+ closePlayer(i);
+ }
+ }
+ });
+ }
}
// 播放器数据, 每一个位置代表页面上行的一个矩形
const playerList: any[] = [];
+function streamProxy(nodeData: any, cb: Function) {
+ let params = {};
+ if (nodeData.nvrIp) {
+ params = {
+ videoIp: nodeData.nvrIp,
+ videoPort: nodeData.nvrPort,
+ factoryNo: nodeData.nvrFactoryNo,
+ account: nodeData.nvrAccount,
+ pwd: nodeData.nvrPwd,
+ channelId: nodeData.nvrChannelNo,
+ };
+ } else {
+ params = {
+ videoIp: nodeData.deviceIp,
+ videoPort: nodeData.devicePort,
+ factoryNo: nodeData.factoryNo,
+ account: nodeData.deviceAccount,
+ pwd: nodeData.devicePwd,
+ channelId: nodeData.channelNo,
+ };
+
+ if (isSupportH265) {
+ addStreamProxy(params).then((res) => cb(res));
+ } else {
+ addFFmpegStreamProxy(params).then((res) => cb(res));
+ }
+ }
+}
/**
* 开始播放视频流
@@ -77,28 +177,8 @@ const playerList: any[] = [];
function doPlayer(nodeData: any, index: number = 0) {
console.log('index=', index);
if (mpegts.isSupported()) {
- let params = {};
- // if (nodeData.nvrIp) {
- // params = {
- // videoIp: nodeData.nvrIp,
- // videoPort: nodeData.nvrPort,
- // factoryNo: nodeData.nvrFactoryNo,
- // account: nodeData.nvrAccount,
- // pwd: nodeData.nvrPwd,
- // channelId: nodeData.nvrChannelNo,
- // };
- // } else {
- params = {
- videoIp: nodeData.deviceIp,
- videoPort: nodeData.devicePort,
- factoryNo: nodeData.factoryNo,
- account: nodeData.deviceAccount,
- pwd: nodeData.devicePwd,
- channelId: nodeData.channelNo,
- };
- // }
- addStreamProxy(params).then((res) => {
- const url = res.wsFlv;
+ streamProxy(nodeData, (res: AddStreamProxyResult) => {
+ const url = res.flv;
// 将url 绑定到 nodeData
nodeData.url = url;
closePlayer(index);
@@ -126,6 +206,7 @@ function doPlayer(nodeData: any, index: number = 0) {
playerList[index] = {
player,
data: nodeData,
+ el: videoElement,
};
} else {
console.log('视频播放元素获取异常');
@@ -136,56 +217,6 @@ function doPlayer(nodeData: any, index: number = 0) {
}
}
-
-function changeElPlayer(playerInfo: any, index: number) {
- const playerData = playerInfo.data;
- const oldPlayer = playerInfo.player;
- if (oldPlayer) {
- closePlayVieo(oldPlayer);
- }
- const videoConfig = {
- type: 'flv',
- url: playerData.url,
- isLive: true,
- hasAudio: false,
- hasVideo: true,
- enableWorker: true, // 启用分离的线程进行转码
- enableStashBuffer: false, // 关闭IO隐藏缓冲区
- stashInitialSize: 256, // 减少首帧显示等待时长
- };
- const playerConfig = {
- enableErrorRecover: true, // 启用错误恢复
- autoCleanupMaxBackwardDuration: 30,
- autoCleanupMinBackwardDuration: 10,
- };
- const player = mpegts.createPlayer(videoConfig, playerConfig);
- const videoElement = itemRefs.value[index];
- if (videoElement) {
- player.attachMediaElement(videoElement);
- player.load();
- player.play();
- playerList[index] = {
- player,
- data: playerData,
- };
- } else {
- console.log('视频播放元素获取异常');
- }
-}
-
-
-function closePlayVieo(plInfo: any) {
- if (plInfo) {
- try {
- plInfo.pause(); // 暂停
- plInfo.unload(); // 卸载
- plInfo.destroy(); // 销毁
- } catch (e) {
- console.log('播放器关闭失败,e=', e);
- }
- }
-}
-
function closePlayer(index: number) {
// 如果播放器存在,尝试关闭
const pData = playerList[index];
@@ -202,8 +233,32 @@ function closePlayer(index: number) {
}
}
+function catchUp() {
+ playerList.forEach((playerData) => {
+ if (playerData) {
+ const { player, el } = playerData;
+ const end = player.buffered.end(player.buffered.length - 1);
+ const diff = end - el.currentTime;
+ if (diff > 2) {
+ // 如果延迟超过2秒
+ el.currentTime = end - 0.5; // 跳转到接近直播点
+ }
+ }
+ });
+}
+let isSupportH265 = false;
+onMounted(() => {
+ // 检测浏览器是否支持h265
+ isSupportH265 = checkHEVCSupport();
+ setInterval(catchUp, 10000);
+});
+onUnmounted(() => {
+ for (let i = 0; i < playerList.length; i++) {
+ closePlayer(i);
+ }
+});
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/level-setting-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/level-setting-modal.vue
new file mode 100644
index 00000000..1568374a
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/level-setting-modal.vue
@@ -0,0 +1,45 @@
+
+
+
+ 特大
+ 重要
+ 一般
+
+
+
+
+
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-detail.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-detail.vue
new file mode 100644
index 00000000..9479a43b
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-detail.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+ {{ warningDetail.alarmId }}
+
+
+ {{ warningDetail.alarmTime }}
+
+
+
+ {{ warningDetail.level }}
+
+
+
+ {{ warningDetail.alarmType }}
+
+
+ {{ warningDetail.description }}
+
+
+ {{ warningDetail.location }}
+
+
+
+ {{ warningDetail.processingStatus }}
+
+
+
+ {{ warningDetail.processingDetails || '-' }}
+
+
+ {{ warningDetail.processingTime || '-' }}
+
+
+ {{ warningDetail.deviceName || '-' }}
+
+
+ {{ warningDetail.expectedProcessingTime || '-' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-modal.vue
new file mode 100644
index 00000000..125a333e
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-modal.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts
index 7639cf63..989bc049 100644
--- a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts
@@ -1,8 +1,9 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
-import { getDictOptions } from '#/utils/dict';
-import { renderDict } from '#/utils/render';
import { h } from 'vue';
+import { getPopupContainer } from '@vben/utils';
+import { getDictOptions } from '#/utils/dict';
+import { DictEnum } from '@vben/constants';
export const querySchema: FormSchemaGetter = () => [
{
@@ -13,11 +14,8 @@ export const querySchema: FormSchemaGetter = () => [
{
component: 'Select',
componentProps: {
- options: [
- { label: '特大', value: '特大' },
- { label: '重要', value: '重要' },
- { label: '一般', value: '一般' },
- ],
+ getPopupContainer,
+ options: getDictOptions(DictEnum.alarm_level),
},
fieldName: 'level',
label: '级别',
@@ -25,13 +23,10 @@ export const querySchema: FormSchemaGetter = () => [
{
component: 'Select',
componentProps: {
- options: [
- { label: '待分配', value: '待分配' },
- { label: '处理中', value: '处理中' },
- { label: '已完成', value: '已完成' },
- ],
+ getPopupContainer,
+ options: getDictOptions(DictEnum.alarm_state),
},
- fieldName: 'processingStatus',
+ fieldName: 'state',
label: '处理状态',
},
];
@@ -40,24 +35,25 @@ export const columns: VxeGridProps['columns'] = [
{ type: 'checkbox', width: 60 },
{
title: '预警编号',
- field: 'alarmId',
- width: 150,
+ field: 'id',
},
{
title: '预警时间',
- field: 'alarmTime',
- width: 150,
+ field: 'reportTime',
+ },
+ {
+ title: '设备名称',
+ field: 'deviceName',
},
{
title: '级别',
field: 'level',
- width: 100,
slots: {
default: ({ row }: any) => {
const levelColors: Record = {
- 特大: 'red',
- 重要: 'orange',
- 一般: 'blue',
+ 1: 'red',
+ 2: 'orange',
+ 3: 'blue',
};
return h(
'span',
@@ -67,59 +63,31 @@ export const columns: VxeGridProps['columns'] = [
fontWeight: 'bold',
},
},
- row.level,
+ row.levelName,
);
},
},
},
{
title: '预警类型',
- field: 'alarmType',
- width: 120,
- },
- {
- title: '描述',
- field: 'description',
- minWidth: 200,
- },
- {
- title: '所在位置',
- field: 'location',
- width: 150,
- },
- {
- title: '处理状态',
- field: 'processingStatus',
- width: 100,
+ field: 'alarmTypeName',
slots: {
default: ({ row }: any) => {
- const statusColors: Record = {
- 待分配: 'red',
- 处理中: 'orange',
- 已完成: 'green',
- };
- return h(
- 'span',
- {
- style: {
- color: statusColors[row.processingStatus] || '#666',
- fontWeight: 'bold',
- },
- },
- row.processingStatus,
- );
+ return h('span', row.bigTypeName + '-' + row.smallTypeName);
},
},
},
{
- title: '处理情况',
- field: 'processingDetails',
- width: 150,
+ title: '处理状态',
+ field: 'stateName',
+ },
+ {
+ title: '预期处理时间',
+ field: 'processSt',
},
{
title: '处理时间',
- field: 'processingTime',
- width: 150,
+ field: 'processEt',
},
{
field: 'action',
@@ -145,6 +113,7 @@ export const modalSchema: FormSchemaGetter = () => [
fieldName: 'alarmId',
component: 'Input',
rules: 'required',
+ disabled: true,
},
{
label: '预警时间',
@@ -156,6 +125,63 @@ export const modalSchema: FormSchemaGetter = () => [
showTime: true,
},
rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '预警类型',
+ fieldName: 'alarmType',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '描述',
+ fieldName: 'description',
+ component: 'Input',
+ formItemClass: 'col-span-2',
+ disabled: true,
+ },
+ {
+ label: '所在位置',
+ fieldName: 'location',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '设备名称',
+ fieldName: 'deviceName',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '处理情况',
+ fieldName: 'processingDetails',
+ component: 'Input',
+ componentProps: {
+ rows: 3,
+ },
+ formItemClass: 'col-span-2',
+ disabled: true,
+ },
+ {
+ label: '处理时间',
+ fieldName: 'processingTime',
+ component: 'DatePicker',
+ componentProps: {
+ format: 'YYYY.MM.DD HH:mm',
+ valueFormat: 'YYYY.MM.DD HH:mm',
+ showTime: true,
+ },
+ disabled: true,
+ },
+ {
+ label: '处理图片',
+ fieldName: 'imgUrl',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
},
{
label: '级别',
@@ -170,27 +196,6 @@ export const modalSchema: FormSchemaGetter = () => [
},
rules: 'selectRequired',
},
- {
- label: '预警类型',
- fieldName: 'alarmType',
- component: 'Input',
- rules: 'required',
- },
- {
- label: '描述',
- fieldName: 'description',
- component: 'InputTextArea',
- componentProps: {
- rows: 3,
- },
- formItemClass: 'col-span-2',
- },
- {
- label: '所在位置',
- fieldName: 'location',
- component: 'Input',
- rules: 'required',
- },
{
label: '处理状态',
fieldName: 'processingStatus',
@@ -205,22 +210,14 @@ export const modalSchema: FormSchemaGetter = () => [
rules: 'selectRequired',
},
{
- label: '处理情况',
- fieldName: 'processingDetails',
- component: 'InputTextArea',
- componentProps: {
- rows: 3,
- },
- formItemClass: 'col-span-2',
- },
- {
- label: '处理时间',
- fieldName: 'processingTime',
+ label: '预期处理时间',
+ fieldName: 'expectedProcessingTime',
component: 'DatePicker',
componentProps: {
format: 'YYYY.MM.DD HH:mm',
valueFormat: 'YYYY.MM.DD HH:mm',
showTime: true,
},
+ rules: 'required',
},
];
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue
index b7ca1380..d15a9ad5 100644
--- a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue
@@ -1,10 +1,146 @@
+
-
+
-
级别设置
-
+ -->
-
+
-
-
-
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/data.ts b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/data.ts
new file mode 100644
index 00000000..a6cae811
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/data.ts
@@ -0,0 +1,265 @@
+import type { FormSchemaGetter } from '#/adapter/form';
+import type { VxeGridProps } from '#/adapter/vxe-table';
+import { getDictOptions } from '#/utils/dict';
+import { renderDict } from '#/utils/render';
+import { h } from 'vue';
+
+export const querySchema: FormSchemaGetter = () => [
+ {
+ component: 'Input',
+ fieldName: 'alarmType',
+ label: '视频预警类型',
+ },
+ {
+ component: 'Select',
+ componentProps: {
+ options: [
+ { label: '特大', value: '特大' },
+ { label: '重要', value: '重要' },
+ { label: '一般', value: '一般' },
+ ],
+ },
+ fieldName: 'level',
+ label: '级别',
+ },
+ {
+ component: 'Select',
+ componentProps: {
+ options: [
+ { label: '待分配', value: '待分配' },
+ { label: '处理中', value: '处理中' },
+ { label: '已完成', value: '已完成' },
+ ],
+ },
+ fieldName: 'processingStatus',
+ label: '处理状态',
+ },
+];
+
+export const columns: VxeGridProps['columns'] = [
+ { type: 'checkbox', width: 60 },
+ {
+ title: '预警编号',
+ field: 'alarmId',
+ width: 150,
+ },
+ {
+ title: '预警时间',
+ field: 'alarmTime',
+ width: 150,
+ },
+ {
+ title: '设备名称',
+ field: 'deviceName',
+ width: 150,
+ },
+ {
+ title: '级别',
+ field: 'level',
+ width: 100,
+ slots: {
+ default: ({ row }: any) => {
+ const levelColors: Record = {
+ 特大: 'red',
+ 重要: 'orange',
+ 一般: 'blue',
+ };
+ return h(
+ 'span',
+ {
+ style: {
+ color: levelColors[row.level] || '#666',
+ fontWeight: 'bold',
+ },
+ },
+ row.level,
+ );
+ },
+ },
+ },
+ {
+ title: '预警类型',
+ field: 'alarmType',
+ width: 120,
+ },
+ {
+ title: '描述',
+ field: 'description',
+ minWidth: 200,
+ },
+ {
+ title: '所在位置',
+ field: 'location',
+ width: 150,
+ },
+ {
+ title: '处理状态',
+ field: 'processingStatus',
+ width: 100,
+ slots: {
+ default: ({ row }: any) => {
+ const statusColors: Record = {
+ 待分配: 'red',
+ 处理中: 'orange',
+ 已完成: 'green',
+ };
+ return h(
+ 'span',
+ {
+ style: {
+ color: statusColors[row.processingStatus] || '#666',
+ fontWeight: 'bold',
+ },
+ },
+ row.processingStatus,
+ );
+ },
+ },
+ },
+ {
+ title: '处理情况',
+ field: 'processingDetails',
+ width: 150,
+ },
+ {
+ title: '预期处理时间',
+ field: 'expectedProcessingTime',
+ width: 150,
+ },
+ {
+ title: '处理时间',
+ field: 'processingTime',
+ width: 150,
+ },
+ {
+ field: 'action',
+ fixed: 'right',
+ slots: { default: 'action' },
+ title: '操作',
+ width: 380,
+ },
+];
+
+export const modalSchema: FormSchemaGetter = () => [
+ {
+ label: '主键',
+ fieldName: 'id',
+ component: 'Input',
+ dependencies: {
+ show: () => false,
+ triggerFields: [''],
+ },
+ },
+ {
+ label: '预警编号',
+ fieldName: 'alarmId',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '预警时间',
+ fieldName: 'alarmTime',
+ component: 'DatePicker',
+ componentProps: {
+ format: 'YYYY.MM.DD HH:mm',
+ valueFormat: 'YYYY.MM.DD HH:mm',
+ showTime: true,
+ },
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '预警类型',
+ fieldName: 'alarmType',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '描述',
+ fieldName: 'description',
+ component: 'Input',
+ formItemClass: 'col-span-2',
+ disabled: true,
+ },
+ {
+ label: '所在位置',
+ fieldName: 'location',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '设备名称',
+ fieldName: 'deviceName',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '处理情况',
+ fieldName: 'processingDetails',
+ component: 'Input',
+ componentProps: {
+ rows: 3,
+ },
+ formItemClass: 'col-span-2',
+ disabled: true,
+ },
+ {
+ label: '处理时间',
+ fieldName: 'processingTime',
+ component: 'DatePicker',
+ componentProps: {
+ format: 'YYYY.MM.DD HH:mm',
+ valueFormat: 'YYYY.MM.DD HH:mm',
+ showTime: true,
+ },
+ disabled: true,
+ },
+ {
+ label: '处理图片',
+ fieldName: 'imgUrl',
+ component: 'Input',
+ rules: 'required',
+ disabled: true,
+ },
+ {
+ label: '级别',
+ fieldName: 'level',
+ component: 'Select',
+ componentProps: {
+ options: [
+ { label: '特大', value: '特大' },
+ { label: '重要', value: '重要' },
+ { label: '一般', value: '一般' },
+ ],
+ },
+ rules: 'selectRequired',
+ },
+ {
+ label: '处理状态',
+ fieldName: 'processingStatus',
+ component: 'Select',
+ componentProps: {
+ options: [
+ { label: '待分配', value: '待分配' },
+ { label: '处理中', value: '处理中' },
+ { label: '已完成', value: '已完成' },
+ ],
+ },
+ rules: 'selectRequired',
+ },
+ {
+ label: '预期处理时间',
+ fieldName: 'expectedProcessingTime',
+ component: 'DatePicker',
+ componentProps: {
+ format: 'YYYY.MM.DD HH:mm',
+ valueFormat: 'YYYY.MM.DD HH:mm',
+ showTime: true,
+ },
+ rules: 'required',
+ },
+];
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/index.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/index.vue
new file mode 100644
index 00000000..cb074052
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/index.vue
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+ {{ $t('pages.common.delete') }}
+
+
+
+
+
+
+
+ {{ $t('pages.common.info') }}
+
+
+ {{ $t('pages.common.edit') }}
+
+
+ 分配处理
+
+
+
+ {{ $t('pages.common.delete') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/level-setting-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/level-setting-modal.vue
new file mode 100644
index 00000000..1568374a
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/level-setting-modal.vue
@@ -0,0 +1,45 @@
+
+
+
+ 特大
+ 重要
+ 一般
+
+
+
+
+
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-detail.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-detail.vue
new file mode 100644
index 00000000..9479a43b
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-detail.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+ {{ warningDetail.alarmId }}
+
+
+ {{ warningDetail.alarmTime }}
+
+
+
+ {{ warningDetail.level }}
+
+
+
+ {{ warningDetail.alarmType }}
+
+
+ {{ warningDetail.description }}
+
+
+ {{ warningDetail.location }}
+
+
+
+ {{ warningDetail.processingStatus }}
+
+
+
+ {{ warningDetail.processingDetails || '-' }}
+
+
+ {{ warningDetail.processingTime || '-' }}
+
+
+ {{ warningDetail.deviceName || '-' }}
+
+
+ {{ warningDetail.expectedProcessingTime || '-' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-modal.vue
new file mode 100644
index 00000000..78c338ea
--- /dev/null
+++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-modal.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/tsconfig.json b/apps/web-antd/tsconfig.json
index 9d43c929..d45e3d7a 100644
--- a/apps/web-antd/tsconfig.json
+++ b/apps/web-antd/tsconfig.json
@@ -4,9 +4,20 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
- "#/*": ["./src/*"]
+ "#/*": [
+ "./src/*"
+ ]
}
},
- "references": [{ "path": "./tsconfig.node.json" }],
- "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "types/**/*.d.ts"]
+ "references": [
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ],
+ "include": [
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ "src/**/*.vue",
+ "types/**/*.d.ts"
+ ]
}
diff --git a/apps/web-antd/vite.config.mts b/apps/web-antd/vite.config.mts
index 29bf5bc4..b55e2848 100644
--- a/apps/web-antd/vite.config.mts
+++ b/apps/web-antd/vite.config.mts
@@ -27,11 +27,7 @@ export default defineConfig(async () => {
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
// mock代理目标地址
- // target: 'http://192.168.43.169:8080',
- // target: 'https://by.missmoc.top/api/',
target: 'http://127.0.0.1:8080',
- // target: 'http://192.168.0.106:8080',
- // target: 'http://47.109.37.87:3010',
ws: true,
},
},
diff --git a/packages/@core/base/shared/src/constants/dict-enum.ts b/packages/@core/base/shared/src/constants/dict-enum.ts
index 457f45ec..c9cd1003 100644
--- a/packages/@core/base/shared/src/constants/dict-enum.ts
+++ b/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -26,6 +26,13 @@ export const DictEnum = {
SIS_ACCESS_CONTROL_DEVICE_TYPE: 'sis_access_control_device_type',
SIS_LIB_TYPE: 'sis_lib_type',
WY_ZCSHZT: 'wy_zcshzt',
+
+ // 事件上报字典key
+ alarm_state: "alarm_state",
+ alarm_level: "alarm_level",
+ event_big_type: "event_big_type",
+ event_small_type: "event_small_type",
+
} as const;
export type DictEnumKey = keyof typeof DictEnum;
类型:已完成
+时间:2025-06-01 11:07:59
+处理人:张三
+类型:处理异常
+时间:2025-06-01 11:07:59
+处理人:张三
+异常原因:时长不够
+类型:处理中
+时间:2025-06-01 11:07:59
+处理人:张三
+类型:创建预警
+时间:2025-06-01 11:07:59
+处理人:张三
+类型:已完成
+时间:2025-06-01 11:07:59
+处理人:张三
+类型:处理异常
+时间:2025-06-01 11:07:59
+处理人:张三
+异常原因:时长不够
+类型:处理中
+时间:2025-06-01 11:07:59
+处理人:张三
+类型:创建预警
+时间:2025-06-01 11:07:59
+处理人:张三
+