flx:新增中水北方考勤 h5监控改成可切换

This commit is contained in:
Rain_ 2025-11-06 17:47:29 +08:00
parent 2649799720
commit c6aecaf5ab
8 changed files with 1990 additions and 47 deletions

View File

@ -604,6 +604,15 @@ const routes2 = [{
"@/views/projectFront/laborManage/attendanceManage/attendanceManageOld.vue"
),
},
//劳务管理--中水北方人员考勤
{
path: "/project/labor/attendanceManageNorth",
name: "劳务管理_中水北方人员考勤",
component: () =>
import (
"@/views/projectFront/laborManage/attendanceManage/attendanceManageNorth.vue"
),
},
{
path: "/project/labor/newAttendanceManage",
name: "劳务管理_人员考勤1",

View File

@ -0,0 +1,144 @@
<template>
<div class="playWnd" :id="`playWnd${itemId}`"></div>
</template>
<script>
let closeVideo = null;
// import {
// OpenVideo,
// unInitObjPlugin,
// InitObjPlugin,
// hidePluginWindow,
// showPluginWindow,
// resizeFn,
// isLoadPlugin,
// setWidthAndHeight,
// setOffset,
// } from "./video_isc_plugin.js";
import VideoPlugin from "./video_isc_plugin.js";
import { getVideoItemInfoPoliceCameraItemApi } from "@/assets/js/api/workTicketManage";
export default {
props: ["devList", "type", "isIframe", "itemId", "equipmentDialog"],
data() {
return {
layout: "1x1",
videoPlugin: null,
};
},
created() {
this.$EventBus.$on("controlVideoShowOrHide", (data) => {
console.log("controlVideoShowOrHide", data);
if (data == "hide") {
this.videoPlugin.hidePluginWindow();
} else {
this.videoPlugin.showPluginWindow();
}
});
},
mounted() {
//
this.videoPlugin = new VideoPlugin();
var layout = "2x2";
if (this.type == "company") {
layout = "4x6";
}
if (this.type.indexOf("x") != -1) {
layout = this.type;
}
this.layout = layout;
console.log("加载isc_plugin.vue");
if (this.devList.length > 0) {
this.devList.forEach((element) => {
this.play(element);
});
}
},
beforeDestroy() {
//
this.videoPlugin.unInitPlugin();
},
methods: {
getPreviewUrl(row) {
let tempCode = row.monitoringNumber;
const param = {
cameraIndexCode: tempCode,
// streamType: row.defaultStreamType == 2 ? 0 : row.defaultStreamType,
type: window.location.protocol.includes("https") ? "wss" : "ws",
transmode: 1,
itemId: row.itemId,
projectSn: row.projectSn,
};
//
return getVideoItemInfoPoliceCameraItemApi(param);
},
play(row) {
this.getPreviewUrl({
...row,
}).then((res) => {
if (res.code !== 200 && !res.result.videoInfo) {
Message.warning("获取视频流失败!");
return;
}
console.log("播放视频", this.itemId);
const dataList = [
{
...row,
...res.result.videoInfo,
...res.result.config,
serialNumber: res.result.videoInfo.monitoringNumber,
defaultStreamType: 2,
},
];
console.log("播放视频2222", dataList);
// 使
this.videoPlugin.initPlugin(this.itemId, res.result.config.appId, res.result.config.appSecret, res.result.config.ip, res.result.config.port, dataList, this.layout)
.then(() => {
console.log('插件初始化成功');
})
.catch(error => {
console.error('插件初始化失败:', error);
});
// isLoadPlugin(dataList, this.layout, this.itemId);
});
},
},
watch: {
//value
devList: {
handler(a, b) {
console.log("isc_plugin.vue获取到设备列表");
//avalueb
if (a.length > 0) {
a.forEach((element) => {
this.play(element);
});
}
},
},
equipmentDialog: {
// immediate: true,
handler(newval) {
console.log("resizeFn", newval, this.videoPlugin);
if (newval) {
this.videoPlugin.hidePluginWindow();
} else {
this.videoPlugin.showPluginWindow();
}
//
// this.videoPlugin.resizePlugin('', this.itemId);
},
},
},
computed: {
isExpand() {
return this.$store.state.isExpand;
},
},
};
</script>
<style lang="scss" scoped>
.playWnd {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,290 @@
import './jsencrypt.min.js';
class VideoPlugin {
constructor() {
this.isChrome = navigator.userAgent.indexOf('Chrome') > -1;
this.WebControl = null;
this.oWebControl = null;
this.pubKey = '';
this.initCount = 0;
this.loadWebControl();
}
async loadWebControl() {
if (this.isChrome) {
try {
const { WebControl } = await
import ('./jsWebControl-1.0.0.min.js');
this.WebControl = WebControl;
} catch (error) {
console.error('加载WebControl失败:', error);
}
}
}
async initPlugin(itemId, appkey, secret, ip, port, videoData, layout) {
if (!this.WebControl) {
console.error('WebControl未加载完成');
return false;
}
// 确保所有必要参数都已初始化
this.appkey = appkey;
this.secret = secret;
this.ip = ip;
this.port = port;
this.layout = layout;
this.width = 0;
this.height = 0;
return new Promise((resolve, reject) => {
this.oWebControl = new this.WebControl({
szPluginContainer: `playWnd${itemId}`,
iServicePortStart: 15900,
iServicePortEnd: 15909,
szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11",
cbConnectSuccess: () => this.onConnectSuccess(itemId, videoData, resolve),
cbConnectError: () => this.onConnectError(itemId, appkey, secret, ip, port, reject),
cbConnectClose: () => console.log("连接关闭")
});
});
}
onConnectSuccess(itemId, videoData, resolve) {
this.setCallbacks();
this.oWebControl.JS_StartService("window", {
dllPath: "./VideoPluginConnect.dll"
}).then(() => {
this.setupWindow(itemId, videoData);
resolve(true);
}).catch(error => {
console.error('启动服务失败:', error);
});
}
onConnectError(itemId, appkey, secret, ip, port, reject) {
console.log("插件未启动,正在尝试启动...");
this.initCount++;
if (this.initCount < 3) {
setTimeout(() => this.initPlugin(itemId, appkey, secret, ip, port), 3000);
} else {
reject(new Error("插件启动失败"));
this.showDownloadDialog();
}
}
setupWindow(itemId, videoData) {
const bottomHeight = 0;
let width = document.getElementById(`videoOverview${itemId}`).offsetWidth;
let height = document.getElementById(`videoOverview${itemId}`).offsetHeight - bottomHeight;
// 缩放比例计算
let ratio = 1;
if (enabledProjectV2 != 1) {
if (localStorage.getItem('systemInfo') && JSON.parse(localStorage.getItem('systemInfo')).zoomType != 1) {
ratio = this.getRatio();
}
}
width = width * ratio;
height = height * ratio;
// 窗口大小调整处理
window.onresize = () => {
clearTimeout(window.$timeId);
window.$timeId = setTimeout(() => {
const container = document.getElementById('videoBoxContainer') || document.querySelector('.videocBox');
if (container) {
width = container.offsetWidth;
height = container.offsetHeight - 80;
}
if (this.oWebControl != null) {
this.oWebControl.JS_Resize(width, height);
}
}, 10);
};
this.oWebControl.JS_CreateWnd(`playWnd${itemId}`, width, height, {
bEmbed: false,
cbSetDocTitle: (uuid) => {
this.oWebControl._pendBg = false;
window.parent.postMessage({
action: 'updateTitle',
msg: '子页面通知父页面修改title',
info: uuid
}, '*');
}
}).then(() => {
console.log("JS_CreateWnd success");
this.initVideo(videoData, itemId);
});
}
initVideo(videoData, itemId) {
this.getPubKey().then(() => {
const config = {
appkey: this.appkey,
secret: this.setEncrypt(this.secret),
ip: this.ip,
playMode: 0,
port: parseInt(this.port),
snapDir: "D:\\SnapDir",
videoDir: "D:\\VideoDir",
layout: this.layout,
enableHTTPS: 1,
encryptedFields: 'secret',
showToolbar: 0,
showSmart: 1,
buttonIDs: "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769"
};
// 添加调试日志
console.log('初始化配置:', config);
console.log('视频数据:', videoData);
this.oWebControl.JS_RequestInterface({
funcName: "init",
argument: JSON.stringify(config)
}).then((response) => {
console.log('初始化响应:', response);
if (COMPANY === 'xingxuan') {
this.oWebControl.oDocOffset.top = 94;
this.oWebControl.oDocOffset.left = 280;
}
console.log("init success", videoData, document.getElementById(`videoOverview${itemId}`), document.getElementById(`videoOverview${itemId}`).width, document.getElementById(`videoOverview${itemId}`).offsetHeight);
// 确保使用最新的width和height
const width = document.getElementById(`videoOverview${itemId}`).offsetWidth;
const height = document.getElementById(`videoOverview${itemId}`).offsetHeight;
this.ratio = window.localStorage.getItem("zoom");
this.oWebControl.JS_Resize(width * this.ratio, height * this.ratio);
this.startVideoPreview(videoData);
});
});
}
startVideoPreview(videoData) {
for (let i = 0; i < videoData.length; i++) {
if (i < 24 && videoData.length >= i) {
this.openVideo(videoData[i].serialNumber, videoData[i].defaultStreamType, i + 1);
}
}
}
openVideo(cameraIndexCode, streamMode, winIndex) {
const transMode = 1; // TCP
const gpuMode = 0; // 不启用GPU硬解
// 添加调试信息
console.log('开始预览:', {
cameraIndexCode,
streamMode,
winIndex,
transMode,
gpuMode
});
this.oWebControl.JS_RequestInterface({
funcName: "startPreview",
argument: JSON.stringify({
cameraIndexCode: cameraIndexCode,
streamMode: streamMode == 2 ? 0 : streamMode,
transMode: transMode,
gpuMode: gpuMode,
wndId: winIndex || -1,
})
}).then((oData) => {
console.log('预览响应:', oData);
});
}
unInitPlugin() {
if (!this.oWebControl) return false;
const isIE = !!window.ActiveXObject || 'ActiveXObject' in window;
if (isIE) {
this.oWebControl.JS_Disconnect().then(() => {
console.log("JS_Disconnect");
});
} else {
this.oWebControl.JS_DestroyWnd().then(() => {
console.log("JS_DestroyWnd");
this.oWebControl.JS_StopService("window").then(() => {
this.oWebControl.JS_Disconnect().then(() => {
console.log("JS_Disconnect");
});
});
});
}
}
setCallbacks() {
this.oWebControl.JS_SetWindowControlCallback({
cbIntegrationCallBack: this.cbIntegrationCallBack
});
}
getRatio() {
const bodyWidth = document.body.clientWidth;
const bodyHeight = document.body.clientHeight;
const scaleWidthNum = bodyWidth / 1920;
const scaleHeightNum = bodyHeight / 1080;
return scaleWidthNum > scaleHeightNum ? scaleHeightNum : scaleWidthNum;
}
setEncrypt(value) {
const encrypt = new JSEncrypt();
encrypt.setPublicKey(this.pubKey);
return encrypt.encrypt(value);
}
getPubKey() {
return new Promise((resolve) => {
this.oWebControl.JS_RequestInterface({
funcName: "getRSAPubKey",
argument: JSON.stringify({ keyLength: 1024 })
}).then((oData) => {
if (oData.responseMsg.data) {
this.pubKey = oData.responseMsg.data;
resolve();
}
});
});
}
cbIntegrationCallBack(oData) {
console.log(JSON.stringify(oData.responseMsg));
}
showDownloadDialog() {
if (confirm("检测到视频插件未安装,是否下载视频插件?")) {
window.location.href = "http://101.43.164.214:11111/image/VideoWebPlugin.rar";
}
}
resizePlugin(val, itemId) {
if (this.oWebControl) {
const width = document.getElementById(`videoOverview${itemId}`).offsetWidth;
const height = document.getElementById(`videoOverview${itemId}`).offsetHeight;
if (val && val == 1) {
this.oWebControl.JS_Resize(width / 2 + 20, height - 215);
} else {
this.oWebControl.JS_Resize(width, height);
}
}
}
hidePluginWindow() {
if (this.oWebControl) {
this.oWebControl.JS_HideWnd();
}
}
showPluginWindow() {
if (this.oWebControl) {
this.oWebControl.JS_ShowWnd();
}
}
setPluginOffset(left, top) {
if (this.WebControl) {
this.WebControl.JS_SetDocOffset({ left, top });
}
}
}
export default VideoPlugin;

View File

@ -286,10 +286,19 @@
:controls="true"
/> -->
<IscPlayer
v-if="videoConfig.enableNotPlugin == 1"
:devList="[item]"
:key="'player-' + item.itemId"
:playerId="'player-' + item.itemId"
/>
<div v-else class="fullHeight videoOverview" :id="`videoOverview${item.itemId}`">
<IscPlugin
:devList="[item]"
:itemId="item.itemId"
:type="'1x1'"
:equipmentDialog="equipmentDialog"
></IscPlugin>
</div>
</div>
<div
class="hls-video_title"
@ -544,6 +553,7 @@ import {
getWorkTicketHistoryListApi,
getVideoItemInfoPoliceCameraItemApi,
} from "@/assets/js/api/workTicketManage";
import { projectVideoConfigListApi } from "@/assets/js/api/equipmentCenter/cameraList";
import { selectAllProjectInfoList } from "@/assets/js/api/companyBigScreen.js";
import { getPoliceCameraItemPageApi } from "@/assets/js/api/bodyWornCamera";
import dayjs from "dayjs";
@ -551,6 +561,7 @@ import duration from "dayjs/plugin/duration";
dayjs.extend(duration);
import store from "@/store";
const BASEURL = store.state.FILEURL;
const workTicketCountList = ref([
{
label: "施工中",
@ -670,7 +681,10 @@ const getWorkTicketPage = () => {
console.log("进来了", Number(res.result.total));
workTicketInfo.total = Number(res.result.total);
if (workTicketList.value.length > 0) {
onViewDetail(workTicketList.value[0]);
onViewDetail(workTicketList.value[0], true);
} else {
workTicketDetail.value = {};
policeCameraItemList.value = [];
}
}
}
@ -706,11 +720,28 @@ const getSelectAllProjectInfoList = () => {
const onSelectProject = () => {
workTicketInfo.pageNo = 1;
workTicketList.value = [];
getProjectVideoConfigList();
getWorkTicketPage();
getWorkTicketCountWorkTicket();
getWorkTicketTypeTreePage();
}
const videoConfig = ref({
enableNotPlugin: 1,
});
//
const getProjectVideoConfigList = () => {
projectVideoConfigListApi({
projectSn: workTicketInfo.projectSn,
}).then((res) => {
if (res.code == 200) {
if (res.result) {
videoConfig.value = res.result;
} else {
videoConfig.enableNotPlugin = 1;
}
}
});
};
const onRefresh = () => {
if(!viewAllShow.value){
onWorkTicketQuery();
@ -782,8 +813,8 @@ const isJSON = (str) => {
};
const timeInterval = ref(null);
//
const onViewDetail = (row) => {
if (row.id == workTicketDetail.value.id) return;
const onViewDetail = (row, flag) => {
if (row.id == workTicketDetail.value.id && flag != true) return;
workTicketDetail.value = row;
getWorkTicketQueryById();
getWorkTicketHistoryList();

View File

@ -278,8 +278,9 @@ export default {
resultList.map((item) => {
return {
...item.videoItem,
videoType: item.projectVideoConfig.videoType,
projectSn: item.projectVideoConfig.projectSn,
...item.projectVideoConfig,
// videoType: item.projectVideoConfig.videoType,
// projectSn: item.projectVideoConfig.projectSn,
};
})
);
@ -323,8 +324,9 @@ export default {
resultList.map((item) => {
return {
...item.videoItem,
videoType: item.projectVideoConfig.videoType,
projectSn: item.projectVideoConfig.projectSn,
...item.projectVideoConfig,
// videoType: item.projectVideoConfig.videoType,
// projectSn: item.projectVideoConfig.projectSn,
};
})
);
@ -404,8 +406,9 @@ export default {
this.$emit("playParams", [
{
...data.videoItem,
videoType: data.projectVideoConfig.videoType,
projectSn: data.projectVideoConfig.projectSn,
...data.projectVideoConfig,
// videoType: data.projectVideoConfig.videoType,
// projectSn: data.projectVideoConfig.projectSn,
},
]);
} else {

View File

@ -118,10 +118,10 @@
<el-tooltip
class="item"
effect="dark"
:content="item.alarmDesc"
:content="item.location"
placement="top-start"
>
<span>{{ $t('message.sixComplete.carDense.from') + ':' }}{{ item.alarmDesc }}</span>
<span>{{ $t('message.sixComplete.carDense.from') + ':' }}{{ item.location }}</span>
</el-tooltip>
</div>
<!-- 去处置 -->

View File

@ -275,7 +275,11 @@
</div>
<el-table :data="realTimeList" class="tables">
<!-- 立杆轴力 -->
<el-table-column align="center" prop="poleAxialForce" label="立杆轴力(N)">
<el-table-column
align="center"
prop="poleAxialForce"
label="立杆轴力(N)"
>
<template #default="{ row }">
<el-input
v-if="row.isRealTimeFlag"
@ -286,7 +290,11 @@
</template>
</el-table-column>
<!-- 水平位移 -->
<el-table-column align="center" prop="horizontalDisplacement" label="水平位移(mm)">
<el-table-column
align="center"
prop="horizontalDisplacement"
label="水平位移(mm)"
>
<template #default="{ row }">
<el-input
v-if="row.isRealTimeFlag"
@ -297,7 +305,11 @@
</template>
</el-table-column>
<!-- 模板沉降 -->
<el-table-column align="center" prop="formworkSettlement" label="模板沉降(mm)">
<el-table-column
align="center"
prop="formworkSettlement"
label="模板沉降(mm)"
>
<template #default="{ row }">
<el-input
v-if="row.isRealTimeFlag"
@ -319,7 +331,11 @@
</template>
</el-table-column>
<!-- 地基沉降 -->
<el-table-column align="center" prop="foundationSettlement" label="地基沉降(mm)">
<el-table-column
align="center"
prop="foundationSettlement"
label="地基沉降(mm)"
>
<template #default="{ row }">
<el-input
v-if="row.isRealTimeFlag"
@ -330,7 +346,11 @@
</template>
</el-table-column>
<!-- 水平倾斜 -->
<el-table-column align="center" prop="horizontalTilt" label="水平倾斜(°)">
<el-table-column
align="center"
prop="horizontalTilt"
label="水平倾斜(°)"
>
<template #default="{ row }">
<el-input
v-if="row.isRealTimeFlag"
@ -353,7 +373,7 @@
value-format="yyyy-MM-dd hh:mm:ss"
type="datetime"
placeholder="测量时间"
style="width: 100%;"
style="width: 100%"
v-model="row.collectTime"
></el-date-picker>
<span v-else>{{ row.collectTime }}</span>
@ -363,7 +383,12 @@
<template #default="{ row, $index }">
<template v-if="row.isRealTimeFlag">
<el-button @click="rowSubmit(row)" type="text">确认</el-button>
<el-button @click="rowConcel(row, $index)" style="margin-left: 10px" type="text">取消</el-button>
<el-button
@click="rowConcel(row, $index)"
style="margin-left: 10px"
type="text"
>取消</el-button
>
</template>
<template v-else>
<el-button
@ -374,7 +399,11 @@
>编辑</el-button
>
<el-button
style="border: 0 !important; color: #f56c6c; margin-left: 10px"
style="
border: 0 !important;
color: #f56c6c;
margin-left: 10px;
"
type="text"
icon="el-icon-delete"
@click="handleDelete(row)"
@ -589,6 +618,11 @@ export default {
type: 5,
warningValue: "",
},
{
alarmValue: "",
type: 6,
warningValue: "",
},
],
},
rules: {
@ -758,6 +792,11 @@ export default {
type: 5,
warningValue: "",
},
{
alarmValue: "",
type: 6,
warningValue: "",
},
],
};
});
@ -793,10 +832,11 @@ export default {
loadRealTimeData() {
let json = Object.assign(
this.filterForm,
{
{
measurePointNumber: this.ruleForm.measurePointNumber,
acquisitionInstrumentNumber: this.ruleForm.acquisitionInstrumentNumber,
},
acquisitionInstrumentNumber:
this.ruleForm.acquisitionInstrumentNumber,
},
{ projectSn: this.$store.state.projectSn }
);
highFormworkMeasureCurrentDataApi(json).then((res) => {
@ -811,28 +851,28 @@ export default {
},
rowSubmit(row) {
const params = {
...this.ruleForm,
...row,
projectSn: this.$store.state.projectSn,
};
if (this.realTimeType == 1) {
delete params.id;
highFormworkMeasureCurrentDataAddApi(params).then((res) => {
if (res.success) {
this.$message.success(res.message);
this.loadRealTimeData();
}
})
} else if (this.realTimeType == 2) {
highFormworkMeasureCurrentDataEditApi(params).then((res) => {
if (res.success) {
this.$message.success(res.message);
this.loadRealTimeData();
}
})
}
...this.ruleForm,
...row,
projectSn: this.$store.state.projectSn,
};
if (this.realTimeType == 1) {
delete params.id;
highFormworkMeasureCurrentDataAddApi(params).then((res) => {
if (res.success) {
this.$message.success(res.message);
this.loadRealTimeData();
}
});
} else if (this.realTimeType == 2) {
highFormworkMeasureCurrentDataEditApi(params).then((res) => {
if (res.success) {
this.$message.success(res.message);
this.loadRealTimeData();
}
});
}
},
rowConcel(row, index){
rowConcel(row, index) {
console.log(row, index);
if (this.realTimeType == 1) {
this.realTimeList.splice(index, 1);
@ -870,9 +910,11 @@ export default {
type: "warning",
})
.then(() => {
highFormworkMeasureCurrentDataDeleteApi({ id: row.id }).then((res) => {
this.loadRealTimeData();
});
highFormworkMeasureCurrentDataDeleteApi({ id: row.id }).then(
(res) => {
this.loadRealTimeData();
}
);
})
.catch(() => {});
},

File diff suppressed because it is too large Load Diff