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 @@
暂无数据
-
+
+
+
+
+
+ {{ node.label }}
+
+ {{ node.label }}
+
+
+
@@ -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`