diff --git a/docsql/2025/12/工区.md b/docsql/2025/12/工区.md new file mode 100644 index 00000000..d346f143 --- /dev/null +++ b/docsql/2025/12/工区.md @@ -0,0 +1,8 @@ +增加表 +sys_work_area + +修改表 +pro_mobile_attendance_data 增加 work_area_id 工区id +attendance_ubi_data 增加 work_area_id 工区id +attendance_ubi_device 增加 work_area_id 工区id +pro_video_monitor 增加 work_area_id 工区id diff --git a/yanzhu-bigscreen/public/index.html b/yanzhu-bigscreen/public/index.html index b37b35a2..ab2f7f65 100644 --- a/yanzhu-bigscreen/public/index.html +++ b/yanzhu-bigscreen/public/index.html @@ -14,10 +14,9 @@ - + diff --git a/yanzhu-bigscreen/src/api/videoMonitor.js b/yanzhu-bigscreen/src/api/videoMonitor.js index 4395fcbe..97a23d58 100644 --- a/yanzhu-bigscreen/src/api/videoMonitor.js +++ b/yanzhu-bigscreen/src/api/videoMonitor.js @@ -12,7 +12,16 @@ const listVideoMonitor = (query) => { method: 'get' }) } + const workAreaTree = (projectId) => { + return request({ + url: '/system/workAarea/workAreaTree?projectId=' + projectId, + method: 'get' + }) +} + + export default { listVideoMonitor, - getYsToken + getYsToken, + workAreaTree } \ No newline at end of file diff --git a/yanzhu-bigscreen/src/views/videoMonitor.vue b/yanzhu-bigscreen/src/views/videoMonitor.vue index 5aa91a4b..6a471881 100644 --- a/yanzhu-bigscreen/src/views/videoMonitor.vue +++ b/yanzhu-bigscreen/src/views/videoMonitor.vue @@ -6,12 +6,23 @@
暂无数据
-
+
{{ it.monitorName }}
+
+ + + +
@@ -62,6 +73,9 @@ export default { showIndex: 1, showList: [], elKey: 0, + showTree: false, + treeData: [], + workAreaOptions: [] } }, mounted() { @@ -106,12 +120,177 @@ export default { return it }) this.showAllVideo() + this.getWorkAreaTree() }) }, + + /** 查询工区树结构 */ + getWorkAreaTree() { + this.$api.videoMonitor.workAreaTree(this.selProject.id).then(response => { + // 转换数据格式以适配el-tree-select组件 + this.workAreaOptions = response.data || []; + if (this.videoMonitors.filter(d => d.workAreaId).length > 0) { + // 调用makeTree函数将videoMonitors挂接到工作区树中 + this.treeData = this.makeTree(); + if (this.treeData.length > 0) { + this.showTree = true; + setTimeout(() => { + this.handleTreeNodeClick(this.treeData[0]); + // 使用ref设置当前选中节点,使默认选中显示样式 + this.$nextTick(() => { + if (this.$refs.treeRef) { + this.$refs.treeRef.setCurrentKey(this.treeData[0].id); + } + }); + }, 400); + } else { + this.showTree = false; + } + } else { + this.treeData = []; + this.showTree = false; + } + }); + }, + + makeTree() { + const videoMonitorMap = {}; + let defNode = { + id: '', + label: '默认工区', + type: 'workArea', + children: [] + } + this.videoMonitors.forEach(video => { + if (video.workAreaId) { + if (!videoMonitorMap[video.workAreaId]) { + videoMonitorMap[video.workAreaId] = []; + } + videoMonitorMap[video.workAreaId].push(video); + } else { + defNode.children.push({ + id: video.id, + label: video.monitorName, + vdata: video, + type: 'workArea', + children: [] + }); + } + }); + + // 第一阶段:递归函数,处理树形结构并添加videoMonitors到所有对应节点 + function attachVideoMonitors(nodes) { + if (!nodes || !Array.isArray(nodes)) return []; + + return nodes.map(node => { + // 深拷贝节点 + const newNode = JSON.parse(JSON.stringify(node)); + + // 添加videoMonitors作为子节点(如果有) + if (videoMonitorMap[node.id] && videoMonitorMap[node.id].length > 0) { + if (!newNode.children) { + newNode.children = []; + } + + // 将videoMonitors添加为子节点 + videoMonitorMap[node.id].forEach(video => { + newNode.children.push({ + id: video.id, + label: video.monitorName, + type: 'workArea', + vdata: video, + children: [] + }); + }); + } + + // 递归处理子节点 + if (newNode.children && newNode.children.length > 0) { + newNode.children = attachVideoMonitors(newNode.children); + } + + return newNode; + }); + } + + // 第二阶段:递归删除不包含videoMonitors的节点(treeNode的type为workArea) + function pruneEmptyNodes(nodes) { + if (!nodes || !Array.isArray(nodes)) return []; + + const result = []; + + for (const node of nodes) { + // 复制节点 + const newNode = { ...node }; + + // 检查节点是否直接包含videoMonitors(通过查看是否有带vdata属性的子节点) + const hasDirectVideoMonitors = node.children && node.children.some(child => child.vdata && child.type === 'workArea'); + + // 递归处理子节点 + if (node.children && node.children.length > 0) { + newNode.children = pruneEmptyNodes(node.children); + } + + // 判断节点是否应该保留: + // 1. 有直接的videoMonitors子节点,或者 + // 2. 有保留下来的子节点(这些子节点可能包含videoMonitors) + if (hasDirectVideoMonitors || (newNode.children && newNode.children.length > 0) || newNode.type === 'workArea') { + result.push(newNode); + } + } + + return result; + } + + // 执行两阶段处理 + const workAreaOptionsCopy = JSON.parse(JSON.stringify(this.workAreaOptions)); + + const treeWithVideos = attachVideoMonitors(workAreaOptionsCopy); + const prunedTree = pruneEmptyNodes(treeWithVideos); + + // 如果默认工区有视频,也添加到结果中 + if (defNode.children && defNode.children.length > 0) { + return [defNode, ...prunedTree]; + } + + return prunedTree; + }, + + handleTreeNodeClick(node) { + // 如果点击的是视频监控节点(包含vdata属性),则选中该视频 + if (node.vdata) { + this.doSelectItem(node.vdata, true); + } else { + //递归获取这个节点的所有视频子节点显示 + let videoNodes = []; + function getVideoNodes(nodes) { + if (!nodes || !Array.isArray(nodes)) return []; + nodes.forEach(node => { + if (node.vdata) { + videoNodes.push(node); + } + if (node.children && node.children.length > 0) { + getVideoNodes(node.children); + } + }); + } + getVideoNodes(node.children); + let videoList = videoNodes.map(d => d.vdata); + this.videoMonitors = videoList; + if (videoList.length > 1) { + this.showMode = 'all'; + this.showAllData(); + } else { + this.showMode = 'sigle'; + this.doSelectItem(videoList[0], true); + } + } + }, + loadVideo(it) { this.$api.videoMonitor.getYsToken(it.id).then((d) => { it.accessToken = d.msg - it.iframeSrc = + it.iframeSrc = 'https://open.ys7.com/ezopen/h5/iframe?url=' + it.url + '&autoplay=1&accessToken=' + d.msg + '&t=' + +new Date() }) }, @@ -120,8 +299,8 @@ export default { this.showIndex = 1 this.showAllData() }, - doSelectItem(it) { - if (it.active) { + doSelectItem(it, reLoad = false) { + if (it.active && !reLoad) { return } this.showMode = 'sigle' @@ -173,6 +352,147 @@ export default { } } } + + .video-tree { + width: 100%; + height: 100%; + font-size: 16px; /* 增大字体大小 */ + .el-tree{ + background: transparent; + color:#fff; + } + .tree-node-content { + display: inline-block; + width: 100%; + padding: 4px 4px; /* 增大内边距 */ + cursor: pointer; + border-radius: 4px; + transition: background-color 0.2s; + line-height: 20px; /* 增大行高 */ + + &:hover { + background-color: transparent; + } + } + .el-tree-node__content{ + &:hover{ + background-color: rgba(255, 255, 255, 0.2); + } + } + + .el-tree-node:focus > .el-tree-node__content { + background-color: rgba(255, 255, 255, 0.2); + } + + .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content { + background-color: rgba(4, 148, 238, 0.787); + color: white; + font-size: 16px; /* 保持选中状态的字体大小 */ + padding: 4px 4px; /* 保持选中状态的内边距 */ + + .el-tree-node__expand-icon, + .el-icon-arrow-right, + .el-icon-arrow-down { + color: white; + font-size: 16px; /* 增大箭头图标大小 */ + } + } + + /* 覆盖默认的el-tree样式以适应大屏 */ + .el-tree-node__content { + padding: 4px 4px; /* 增大节点内容的内边距 */ + height: auto; /* 允许内容高度自适应 */ + } + + .el-tree-node__expand-icon { + font-size: 16px; /* 增大展开/折叠图标大小 */ + width: 24px; /* 增大图标容器宽度 */ + height: 24px; /* 增大图标容器高度 */ + line-height: 20px; /* 调整图标行高 */ + } + + .el-tree-node__label { + font-size: 16px; /* 确保标签字体大小一致 */ + } + } + + /* 针对大屏分辨率的额外调整 */ + @media (min-width: 1921px) and (max-width: 2560px) { + .video-tree { + font-size: 18px; /* 更大屏显时的字体 */ + + .tree-node-content { + padding: 8px 4px; /* 更大的内边距 */ + line-height: 32px; /* 更大的行高 */ + } + + .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content { + font-size: 18px; + padding: 8px 4px; + + .el-tree-node__expand-icon, + .el-icon-arrow-right, + .el-icon-arrow-down { + font-size: 18px; + } + } + + .el-tree-node__content { + padding: 8px 4px; + line-height: 24px; + } + + .el-tree-node__expand-icon { + font-size: 18px; + width: 24px; + height: 24px; + line-height: 24px; + } + + .el-tree-node__label { + font-size: 18px; + } + } + } + + /* 针对大屏分辨率的额外调整 */ + @media (min-width: 2561px) { + .video-tree { + font-size: 24px; /* 更大屏显时的字体 */ + + .tree-node-content { + padding: 8px 4px; /* 更大的内边距 */ + line-height: 32px; /* 更大的行高 */ + } + + .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content { + font-size: 24px; + padding: 8px 4px; + + .el-tree-node__expand-icon, + .el-icon-arrow-right, + .el-icon-arrow-down { + font-size: 18px; + } + } + + .el-tree-node__content { + padding: 8px 4px; + line-height: 24px; + } + + .el-tree-node__expand-icon { + font-size: 24px; + width: 24px; + height: 24px; + line-height: 24px; + } + + .el-tree-node__label { + font-size: 24px; + } + } + } .all-mode { .all-header { diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiData.java b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiData.java index 1e59f615..73213108 100644 --- a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiData.java +++ b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiData.java @@ -76,6 +76,16 @@ public class AttendanceUbiData extends BaseEntity @Excel(name = "设备NO") private String deviceNo; + private Long workAreaId; + + public Long getWorkAreaId() { + return workAreaId; + } + + public void setWorkAreaId(Long workAreaId) { + this.workAreaId = workAreaId; + } + /** $column.columnComment */ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") private Long isDel; diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiDevice.java b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiDevice.java index 9ea2c1be..2489d2b1 100644 --- a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiDevice.java +++ b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/AttendanceUbiDevice.java @@ -100,6 +100,10 @@ public class AttendanceUbiDevice extends BaseEntity @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") private Long isDel; + /** 工区ID */ + @Excel(name = "工区ID") + private Long workAreaId; + private String compName; private String projectName; @@ -148,6 +152,7 @@ public class AttendanceUbiDevice extends BaseEntity private String souceName; + private String workAreaName; // 工区名称,用于显示 public void setId(Long id) { this.id = id; @@ -337,6 +342,24 @@ public class AttendanceUbiDevice extends BaseEntity { return isDel; } + + public void setWorkAreaId(Long workAreaId) + { + this.workAreaId = workAreaId; + } + + public Long getWorkAreaId() + { + return workAreaId; + } + + public String getWorkAreaName() { + return workAreaName; + } + + public void setWorkAreaName(String workAreaName) { + this.workAreaName = workAreaName; + } @Override public String toString() { diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java index 0c08db42..40ba49dd 100644 --- a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java +++ b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java @@ -91,6 +91,16 @@ public class ProMobileAttendanceData extends BaseEntity @Excel(name = "考勤设备") private String attDevice; + private Long workAreaId; + + public Long getWorkAreaId() { + return workAreaId; + } + + public void setWorkAreaId(Long workAreaId) { + this.workAreaId = workAreaId; + } + public String getAttDevice() { return attDevice; } diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDataMapper.xml b/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDataMapper.xml index d50c880d..642f7b73 100644 --- a/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDataMapper.xml +++ b/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDataMapper.xml @@ -33,17 +33,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + select id, comId, projectId, userId, userName, sub_dept_group, sub_dept_group_name, craft_type, craft_post,admitGuid, - eventGuid,inPhoto,outPhoto,comName,projectName,sub_dept_id,sub_dept_name, + eventGuid,inPhoto,outPhoto,comName,projectName,sub_dept_id,sub_dept_name,work_area_id, inTime, outTime, deviceNo, is_del, state, remark, create_by, create_time, update_by, update_time from attendance_ubi_data select id, comId, projectId, userId, userName, sub_dept_group, sub_dept_group_name, craft_type, craft_post,admitGuid, - eventGuid,inPhoto,outPhoto,inData,outData,comName,projectName,sub_dept_id,sub_dept_name, + eventGuid,inPhoto,outPhoto,inData,outData,comName,projectName,sub_dept_id,sub_dept_name,work_area_id, inTime, outTime, deviceNo, is_del, state, remark, create_by, create_time, update_by, update_time from attendance_ubi_data @@ -133,6 +134,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" inData, outTime, outData, + work_area_id, deviceNo, is_del, sub_dept_id, @@ -163,6 +165,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{inData}, #{outTime}, #{outData}, + #{workAreaId}, #{deviceNo}, #{isDel}, #{subDeptId}, diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDeviceMapper.xml b/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDeviceMapper.xml index 7b50efb5..ecd9b0b8 100644 --- a/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDeviceMapper.xml +++ b/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/AttendanceUbiDeviceMapper.xml @@ -36,17 +36,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + select ud.id, ud.com_id, ud.project_id, ud.name, ud.tag, ud.scene_guid, ud.source, ud.device_no, ud.addition, ud.bind_default_scene, ud.force_empty_device, ud.direction,ud.channel, + ud.work_area_id, ud.device_model, ud.device_state, ud.rec_type, ud.online_state, ud.version_no, ud.last_active_time, ud.has_register, ud.state, ud.remark, ud.is_del, - ud.create_by, ud.create_time, ud.update_by, ud.update_time ,dp.`dept_name` comp_name,pp.`project_name`,dic.`dict_label` souce_name + ud.create_by, ud.create_time, ud.update_by, ud.update_time ,dp.`dept_name` comp_name,pp.`project_name`,dic.`dict_label` souce_name,wa.`title` work_area_name from attendance_ubi_device ud left join sys_dept dp on ud.`com_id`=dp.`dept_id` left join pro_project_info pp on ud.`project_id`=pp.`id` left join sys_dict_data dic on ud.`source`=dic.`dict_value` and dic.`dict_type`='ubi_device_source' + left join sys_work_area wa on ud.`work_area_id`=wa.`id`